# fsverity-utils

## Introduction

This is fsverity-utils, a set of userspace utilities for fs-verity.
fs-verity is a Linux kernel feature that does transparent on-demand
integrity/authenticity verification of the contents of read-only
files, using a hidden Merkle tree (hash tree) associated with the
file.  It is similar to dm-verity, but implemented at the file level
rather than at the block device level.  See the [kernel
documentation](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html)
for more information about fs-verity, including which filesystems
support it.

fsverity-utils currently contains just one program, `fsverity`.  The
`fsverity` program allows you to set up fs-verity protected files.
In addition, the file digest computation and signing functionality of
`fsverity` is optionally exposed through a C library `libfsverity`.
See `libfsverity.h` for the API of this library.

## Building and installing

To build fsverity-utils, first install the needed build dependencies.  For
example, on Debian-based systems, run:

```bash
    sudo apt-get install libssl-dev
```

OpenSSL must be version 1.0.0 or later.  This is the only runtime dependency.

Then, to build and install fsverity-utils:

```bash
    make
    sudo make install
```

By default, the following targets are built and installed: the program
`fsverity`, the static library `libfsverity.a`, the shared library
`libfsverity.so`, and the manual page `fsverity.1`.  You can also run
`make check` to build and run the tests, or `make help` to display all
available build targets.

By default, `fsverity` is statically linked to `libfsverity`.  You can
use `make USE_SHARED_LIB=1` to use dynamic linking instead.

See the `Makefile` for other supported build and installation options.

### Building on Windows

There is minimal support for building Windows executables using MinGW.
```bash
    make CC=x86_64-w64-mingw32-gcc
```

`fsverity.exe` will be built, and it supports the `digest` and `sign` commands.

A Windows build of OpenSSL/libcrypto needs to be available.

## Examples

Full usage information for `fsverity` can be found in the manual page
(`man fsverity`).  Here, we just show some typical examples.

### Basic use

```bash
    mkfs.ext4 -O verity /dev/vdc
    mount /dev/vdc /vdc
    cd /vdc

    # Create a test file
    head -c 1000000 /dev/urandom > file
    sha256sum file

    # Enable verity on the file
    fsverity enable file

    # Show the verity file digest
    fsverity measure file

    # File should still be readable as usual.  However, all data read
    # is now transparently checked against a hidden Merkle tree, whose
    # root hash is incorporated into the verity file digest.  Reads of
    # any corrupted parts of the data will fail.
    sha256sum file
```

Note that in the above example, the file isn't signed.  Therefore, to
get any authenticity protection (as opposed to just integrity
protection), the output of `fsverity measure` needs to be compared
against a trusted value.

### With IMA

Since Linux v5.19, the kernel's IMA (Integrity Measurement
Architecture) subsystem supports using fs-verity file digests in lieu
of traditional file digests.  This must be configured in the IMA
policy.  For more information, see the IMA documentation.

### Using builtin signatures

First, note that fs-verity is essentially just a way of hashing a
file; it doesn't mandate a specific way of handling signatures.
There are several possible ways that signatures could be handled:

* Do it entirely in userspace
* Use IMA appraisal
* Use fs-verity built-in signatures

Any such solution needs two parts: (a) a policy that determines which
files are required to have fs-verity enabled and have a valid
signature, and (b) enforcement of the policy.  Each part could happen
either in a trusted userspace program(s) or in the kernel.

fs-verity built-in signatures (which are supported when the kernel was
built with `CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y`) are a hybrid
solution where the policy of which files are required to be signed is
determined and enforced by a trusted userspace program, but the actual
signature verification happens in the kernel.  Specifically, with
built-in signatures, the filesystem supports storing a signed file
digest in each file's verity metadata.  Before allowing access to the
file, the filesystem will automatically verify the signature against
the set of X.509 certificates in the ".fs-verity" kernel keyring.  If
set, the sysctl `fs.verity.require_signatures=1` will make the kernel
enforce that every verity file has a valid built-in signature.

fs-verity built-in signatures are primarily intended as a
proof-of-concept; they reuse the kernel code that verifies the
signatures of loadable kernel modules.  This solution still requires a
trusted userspace program to enforce that particular files have
fs-verity enabled.  Also, this solution uses PKCS#7 signatures, which
are complex and prone to security bugs.

Thus, if possible one of the other solutions should be used instead.
For example, the trusted userspace program could verify signatures
itself, using a simple signature format using a modern algorithm such
as Ed25519.

That being said, here are some examples of using built-in signatures:

```bash
    # Generate a new certificate and private key:
    openssl req -newkey rsa:4096 -nodes -keyout key.pem -x509 -out cert.pem

    # Convert the certificate from PEM to DER format:
    openssl x509 -in cert.pem -out cert.der -outform der

    # Load the certificate into the fs-verity keyring:
    keyctl padd asymmetric '' %keyring:.fs-verity < cert.der

    # Optionally, lock the keyring so that no more keys can be added
    # (requires keyctl v1.5.11 or later):
    keyctl restrict_keyring %keyring:.fs-verity

    # Optionally, require that all verity files be signed:
    sysctl fs.verity.require_signatures=1

    # Now set up fs-verity on a test file:
    sha256sum file
    fsverity sign file file.sig --key=key.pem --cert=cert.pem
    fsverity enable file --signature=file.sig
    rm -f file.sig
    sha256sum file

    # The digest to be signed can also be printed separately, hex
    # encoded, in case the integrated signing cannot be used:
    fsverity digest file --compact --for-builtin-sig | tr -d '\n' | xxd -p -r | openssl smime -sign -in /dev/stdin ...
```

## Notices

fsverity-utils is provided under the terms of the MIT license.  A copy
of this license can be found in the file named [LICENSE](LICENSE).

Send questions and bug reports to fsverity@lists.linux.dev.

Signed release tarballs for fsverity-utils can be found on
[kernel.org](https://kernel.org/pub/linux/kernel/people/ebiggers/fsverity-utils/).

## Contributing

Send patches to fsverity@lists.linux.dev with the additional tag
`fsverity-utils` in the subject, i.e. `[fsverity-utils PATCH]`.
Patches should follow the Linux kernel's coding style.  A
`.clang-format` file is provided to approximate this coding style;
consider using `git clang-format`.  Additionally, like the Linux
kernel itself, patches require the following "sign-off" procedure:

The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right
to pass it on as an open-source patch.  The rules are pretty simple:
if you can certify the below:

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

        (a) The contribution was created in whole or in part by me and I
            have the right to submit it under the open source license
            indicated in the file; or

        (b) The contribution is based upon previous work that, to the best
            of my knowledge, is covered under an appropriate open source
            license and I have the right under that license to submit that
            work with modifications, whether created in whole or in part
            by me, under the same open source license (unless I am
            permitted to submit under a different license), as indicated
            in the file; or

        (c) The contribution was provided directly to me by some other
            person who certified (a), (b) or (c) and I have not modified
            it.

        (d) I understand and agree that this project and the contribution
            are public and that a record of the contribution (including all
            personal information I submit with it, including my sign-off) is
            maintained indefinitely and may be redistributed consistent with
            this project or the open source license(s) involved.

then you just add a line saying::

	Signed-off-by: Random J Developer <random@developer.example.org>

using your real name (sorry, no pseudonyms or anonymous contributions.)
