Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 981bfe68 authored by Eric Biggers's avatar Eric Biggers Committed by Jaegeuk Kim
Browse files

fs-verity: add Kconfig and the helper functions for hashing



Add the beginnings of the fs/verity/ support layer, including the
Kconfig option and various helper functions for hashing.  To start, only
SHA-256 is supported, but other hash algorithms can easily be added.

Reviewed-by: default avatarTheodore Ts'o <tytso@mit.edu>
Reviewed-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent 375b9e1f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -105,6 +105,8 @@ config MANDATORY_FILE_LOCKING

source "fs/crypto/Kconfig"

source "fs/verity/Kconfig"

source "fs/notify/Kconfig"

source "fs/quota/Kconfig"
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
obj-$(CONFIG_AIO)               += aio.o
obj-$(CONFIG_FS_DAX)		+= dax.o
obj-$(CONFIG_FS_ENCRYPTION)	+= crypto/
obj-$(CONFIG_FS_VERITY)		+= verity/
obj-$(CONFIG_FILE_LOCKING)      += locks.o
obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o

fs/verity/Kconfig

0 → 100644
+38 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0

config FS_VERITY
	bool "FS Verity (read-only file-based authenticity protection)"
	select CRYPTO
	# SHA-256 is selected as it's intended to be the default hash algorithm.
	# To avoid bloat, other wanted algorithms must be selected explicitly.
	select CRYPTO_SHA256
	help
	  This option enables fs-verity.  fs-verity is the dm-verity
	  mechanism implemented at the file level.  On supported
	  filesystems (currently EXT4 and F2FS), userspace can use an
	  ioctl to enable verity for a file, which causes the filesystem
	  to build a Merkle tree for the file.  The filesystem will then
	  transparently verify any data read from the file against the
	  Merkle tree.  The file is also made read-only.

	  This serves as an integrity check, but the availability of the
	  Merkle tree root hash also allows efficiently supporting
	  various use cases where normally the whole file would need to
	  be hashed at once, such as: (a) auditing (logging the file's
	  hash), or (b) authenticity verification (comparing the hash
	  against a known good value, e.g. from a digital signature).

	  fs-verity is especially useful on large files where not all
	  the contents may actually be needed.  Also, fs-verity verifies
	  data each time it is paged back in, which provides better
	  protection against malicious disks vs. an ahead-of-time hash.

	  If unsure, say N.

config FS_VERITY_DEBUG
	bool "FS Verity debugging"
	depends on FS_VERITY
	help
	  Enable debugging messages related to fs-verity by default.

	  Say N unless you are an fs-verity developer.

fs/verity/Makefile

0 → 100644
+4 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0

obj-$(CONFIG_FS_VERITY) += hash_algs.o \
			   init.o
+88 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * fs-verity: read-only file-based authenticity protection
 *
 * Copyright 2019 Google LLC
 */

#ifndef _FSVERITY_PRIVATE_H
#define _FSVERITY_PRIVATE_H

#ifdef CONFIG_FS_VERITY_DEBUG
#define DEBUG
#endif

#define pr_fmt(fmt) "fs-verity: " fmt

#include <crypto/sha.h>
#include <linux/fs.h>
#include <uapi/linux/fsverity.h>

struct ahash_request;

/*
 * Implementation limit: maximum depth of the Merkle tree.  For now 8 is plenty;
 * it's enough for over U64_MAX bytes of data using SHA-256 and 4K blocks.
 */
#define FS_VERITY_MAX_LEVELS		8

/*
 * Largest digest size among all hash algorithms supported by fs-verity.
 * Currently assumed to be <= size of fsverity_descriptor::root_hash.
 */
#define FS_VERITY_MAX_DIGEST_SIZE	SHA256_DIGEST_SIZE

/* A hash algorithm supported by fs-verity */
struct fsverity_hash_alg {
	struct crypto_ahash *tfm; /* hash tfm, allocated on demand */
	const char *name;	  /* crypto API name, e.g. sha256 */
	unsigned int digest_size; /* digest size in bytes, e.g. 32 for SHA-256 */
	unsigned int block_size;  /* block size in bytes, e.g. 64 for SHA-256 */
};

/* Merkle tree parameters: hash algorithm, initial hash state, and topology */
struct merkle_tree_params {
	const struct fsverity_hash_alg *hash_alg; /* the hash algorithm */
	const u8 *hashstate;		/* initial hash state or NULL */
	unsigned int digest_size;	/* same as hash_alg->digest_size */
	unsigned int block_size;	/* size of data and tree blocks */
	unsigned int hashes_per_block;	/* number of hashes per tree block */
	unsigned int log_blocksize;	/* log2(block_size) */
	unsigned int log_arity;		/* log2(hashes_per_block) */
	unsigned int num_levels;	/* number of levels in Merkle tree */
	u64 tree_size;			/* Merkle tree size in bytes */

	/*
	 * Starting block index for each tree level, ordered from leaf level (0)
	 * to root level ('num_levels - 1')
	 */
	u64 level_start[FS_VERITY_MAX_LEVELS];
};

/* hash_algs.c */

extern struct fsverity_hash_alg fsverity_hash_algs[];

const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
						      unsigned int num);
const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg,
				      const u8 *salt, size_t salt_size);
int fsverity_hash_page(const struct merkle_tree_params *params,
		       const struct inode *inode,
		       struct ahash_request *req, struct page *page, u8 *out);
int fsverity_hash_buffer(const struct fsverity_hash_alg *alg,
			 const void *data, size_t size, u8 *out);
void __init fsverity_check_hash_algs(void);

/* init.c */

extern void __printf(3, 4) __cold
fsverity_msg(const struct inode *inode, const char *level,
	     const char *fmt, ...);

#define fsverity_warn(inode, fmt, ...)		\
	fsverity_msg((inode), KERN_WARNING, fmt, ##__VA_ARGS__)
#define fsverity_err(inode, fmt, ...)		\
	fsverity_msg((inode), KERN_ERR, fmt, ##__VA_ARGS__)

#endif /* _FSVERITY_PRIVATE_H */
Loading