Convert fs/verity/ to use SHA-2 library API
Subsystems (5)
Eric Biggers
maintainercover Convert fs/verity/ to use SHA-2 library API
This series, including all its prerequisites, is also available at:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git fsverity-libcrypto-v1
This series makes fs/verity/ use the SHA-2 library API instead of the old-school crypto API. This is simpler and more efficient.
This depends on my SHA-2 library improvements for 6.17 (many patches), so this patchset might need to wait until 6.18. But I'm also thinking about just basing the fsverity tree on libcrypto-next for 6.17.
Eric Biggers (2):
lib/crypto: hash_info: Move hash_info.c into lib/crypto/
fsverity: Switch from crypto_shash to SHA-2 library
Documentation/filesystems/fsverity.rst | 3 +-
crypto/Kconfig | 3 -
crypto/Makefile | 1 -
fs/verity/Kconfig | 6 +-
fs/verity/enable.c | 8 +-
fs/verity/fsverity_private.h | 24 +--
fs/verity/hash_algs.c | 194 +++++++++----------------
fs/verity/open.c | 36 ++---
fs/verity/verify.c | 7 +-
lib/crypto/Kconfig | 3 +
lib/crypto/Makefile | 2 +
{crypto => lib/crypto}/hash_info.c | 0
12 files changed, 107 insertions(+), 180 deletions(-)
rename {crypto => lib/crypto}/hash_info.c (100%)Signature · 1 line
2.50.0
Eric Biggers
maintainerPATCH 1/2 lib/crypto: hash_info: Move hash_info.c into lib/crypto/
crypto/hash_info.c just contains a couple of arrays that map HASH_ALGO_* algorithm IDs to properties of those algorithms. It is compiled only when CRYPTO_HASH_INFO=y, but currently CRYPTO_HASH_INFO depends on CRYPTO. Since this can be useful without the old-school crypto API, move it into lib/crypto/ so that it no longer depends on CRYPTO.
This eliminates the need for FS_VERITY to select CRYPTO after it's been converted to use lib/crypto/.
---
crypto/Kconfig | 3 ---
crypto/Makefile | 1 -
lib/crypto/Kconfig | 3 +++
lib/crypto/Makefile | 2 ++
{crypto => lib/crypto}/hash_info.c | 0
5 files changed, 5 insertions(+), 4 deletions(-)
rename {crypto => lib/crypto}/hash_info.c (100%)crypto/Kconfig +0 -3
@@ -1420,13 +1420,10 @@ config CRYPTO_USER_API_ENABLE_OBSOLETE already been phased out from internal use by the kernel, and are only useful for userspace clients that still rely on them. endmenu -config CRYPTO_HASH_INFO - bool - if !KMSAN # avoid false positives from assembly if ARM source "arch/arm/crypto/Kconfig" endif if ARM64
crypto/Makefile +0 -1
@@ -202,11 +202,10 @@ obj-$(CONFIG_CRYPTO_ECRDSA) += ecrdsa_generic.o # generic algorithms and the async_tx api # obj-$(CONFIG_XOR_BLOCKS) += xor.o obj-$(CONFIG_ASYNC_CORE) += async_tx/ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ -obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o crypto_simd-y := simd.o obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o # # Key derivation function
lib/crypto/Kconfig +3 -0
@@ -3,10 +3,13 @@ menu "Crypto library routines" config CRYPTO_LIB_UTILS tristate +config CRYPTO_HASH_INFO + bool + config CRYPTO_LIB_AES tristate config CRYPTO_LIB_AESCFB tristate
lib/crypto/Makefile +2 -0
@@ -6,10 +6,12 @@ quiet_cmd_perlasm = PERLASM $@ cmd_perlasm = $(PERL) $(<) > $(@) quiet_cmd_perlasm_with_args = PERLASM $@ cmd_perlasm_with_args = $(PERL) $(<) void $(@) +obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o + obj-$(CONFIG_CRYPTO_LIB_UTILS) += libcryptoutils.o libcryptoutils-y := memneq.o utils.o # chacha is used by the /dev/random driver which is always builtin obj-y += chacha.o
lib/crypto/hash_info.c renamed from crypto/hash_info.c +0 -0
Signature · 1 line
2.50.0
Eric Biggers
maintainerPATCH 2/2 fsverity: Switch from crypto_shash to SHA-2 library
In reply to Eric Biggersfsverity supports two hash algorithms: SHA-256 and SHA-512. Since both of these have a library API now, just use the library API instead of crypto_shash. Even with multiple algorithms, the library-based code still ends up being quite a bit simpler, due to how clumsy the old-school crypto API is. The library-based code is also more efficient, since it avoids overheads such as indirect calls.
--- Documentation/filesystems/fsverity.rst | 3 +- fs/verity/Kconfig | 6 +- fs/verity/enable.c | 8 +- fs/verity/fsverity_private.h | 24 +-- fs/verity/hash_algs.c | 194 +++++++++---------------- fs/verity/open.c | 36 ++--- fs/verity/verify.c | 7 +- 7 files changed, 102 insertions(+), 176 deletions(-)
Documentation/filesystems/fsverity.rst +1 -2
@@ -183,12 +183,11 @@ FS_IOC_ENABLE_VERITY can fail with the following errors: - ``EKEYREJECTED``: the builtin signature doesn't match the file - ``EMSGSIZE``: the salt or builtin signature is too long - ``ENOKEY``: the ".fs-verity" keyring doesn't contain the certificate needed to verify the builtin signature - ``ENOPKG``: fs-verity recognizes the hash algorithm, but it's not - available in the kernel's crypto API as currently configured (e.g. - for SHA-512, missing CONFIG_CRYPTO_SHA512). + available in the kernel as currently configured - ``ENOTTY``: this type of filesystem does not implement fs-verity - ``EOPNOTSUPP``: the kernel was not configured with fs-verity support; or the filesystem superblock has not had the 'verity' feature enabled on it; or the filesystem does not support fs-verity on this file. (See `Filesystem support`_.)
fs/verity/Kconfig +2 -4
@@ -1,14 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 config FS_VERITY bool "FS Verity (read-only file-based authenticity protection)" - select CRYPTO select CRYPTO_HASH_INFO - # 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 + select CRYPTO_LIB_SHA256 + select CRYPTO_LIB_SHA512 help This option enables fs-verity. fs-verity is the dm-verity mechanism implemented at the file level. On supported filesystems (currently ext4, f2fs, and btrfs), userspace can use an ioctl to enable verity for a file, which causes the
fs/verity/enable.c +2 -6
@@ -5,11 +5,10 @@* Copyright 2019 Google LLC */ #include "fsverity_private.h" -#include <crypto/hash.h> #include <linux/mount.h> #include <linux/sched/signal.h> #include <linux/uaccess.h> struct block_buffer {
@@ -22,11 +21,10 @@ struct block_buffer {static int hash_one_block (struct inode *inode,const struct merkle_tree_params *params,struct block_buffer *cur) {struct block_buffer *next = cur +1 ; -int err;/* * Safety check to prevent a buffer overflow in case of a filesystem bug * that allows the file size to change despite deny_write_access(), or a * bug in the Merkle tree logic itself
@@ -35,14 +33,12 @@ static int hash_one_block(struct inode *inode,return -EINVAL ;/* Zero-pad the block if it's shorter than the block size. */ memset (&cur->data[cur->filled],0 , params->block_size - cur->filled); - err =fsverity_hash_block (params, inode, cur->data, - &next->data[next->filled]); -if (err) -return err; +fsverity_hash_block (params, inode, cur->data, + &next->data[next->filled]); next->filled += params->digest_size; cur->filled =0 ;return 0 ; }
fs/verity/fsverity_private.h +15 -9
@@ -18,25 +18,30 @@*/ #define FS_VERITY_MAX_LEVELS 8/* A hash algorithm supported by fs-verity */ struct fsverity_hash_alg { -struct crypto_shash *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 */ /* * The HASH_ALGO_* constant for this algorithm. This is different from * FS_VERITY_HASH_ALG_*, which uses a different numbering scheme. */ enum hash_algo algo_id; }; +union fsverity_hash_ctx { +struct sha256_ctx sha256; +struct sha512_ctx sha512; +}; +/* 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 */ +/* initial hash state if salted, NULL if unsalted */ +const union fsverity_hash_ctx *hashstate;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 blocks_per_page;/* PAGE_SIZE / block_size */ u8 log_digestsize;/* log2(digest_size) */
@@ -74,20 +79,21 @@ struct fsverity_info {#define FS_VERITY_MAX_SIGNATURE_SIZE (FS_VERITY_MAX_DESCRIPTOR_SIZE - \ sizeof(struct fsverity_descriptor))/* hash_algs.c */ -extern struct fsverity_hash_alg fsverity_hash_algs[]; +extern const 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_block (const struct merkle_tree_params *params, -const struct inode *inode,const void *data,u8 *out); -int fsverity_hash_buffer (const struct fsverity_hash_alg *alg, -const void *data,size_t size,u8 *out); +union fsverity_hash_ctx * +fsverity_prepare_hash_state (const struct fsverity_hash_alg *alg, +const u8 *salt,size_t salt_size); +void fsverity_hash_block (const struct merkle_tree_params *params, +const struct inode *inode,const void *data,u8 *out); +void 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 */ void __printf(3, 4) __cold
fs/verity/hash_algs.c +66 -128
274 lines not on this page · raw message
fs/verity/open.c +14 -22
@@ -40,22 +40,22 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,int level;memset (params,0 ,sizeof (*params)); hash_alg =fsverity_get_hash_alg (inode, hash_algorithm); -if (IS_ERR (hash_alg)) -return PTR_ERR (hash_alg); +if (!hash_alg) +return -EINVAL ; params->hash_alg = hash_alg; params->digest_size = hash_alg->digest_size; - params->hashstate =fsverity_prepare_hash_state (hash_alg, salt, - salt_size); -if (IS_ERR (params->hashstate)) { - err =PTR_ERR (params->hashstate); - params->hashstate =NULL ; -fsverity_err (inode,"Error %d preparing hash state" , err); - goto out_err; +if (salt_size) { + params->hashstate = +fsverity_prepare_hash_state (hash_alg, salt, salt_size); +if (!params->hashstate) { + err = -ENOMEM ; + goto out_err; + } }/* * fs/verity/ directly assumes that the Merkle tree block size is a * power of 2 less than or equal to PAGE_SIZE. Another restriction
@@ -156,22 +156,19 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,/* * Compute the file digest by hashing the fsverity_descriptor excluding the * builtin signature and with the sig_size field set to 0. */ -static int compute_file_digest (const struct fsverity_hash_alg *hash_alg, -struct fsverity_descriptor *desc, -u8 *file_digest) +static void compute_file_digest (const struct fsverity_hash_alg *hash_alg, +struct fsverity_descriptor *desc, +u8 *file_digest) {__le32 sig_size = desc->sig_size; -int err; desc->sig_size =0 ; - err =fsverity_hash_buffer (hash_alg, desc,sizeof (*desc), file_digest); +fsverity_hash_buffer (hash_alg, desc,sizeof (*desc), file_digest); desc->sig_size = sig_size; - -return err; }/* * Create a new fsverity_info from the given fsverity_descriptor (with optional * appended builtin signature), and check the signature if present. The
@@ -199,16 +196,11 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode, goto fail; }memcpy (vi->root_hash, desc->root_hash, vi->tree_params.digest_size); - err =compute_file_digest (vi->tree_params.hash_alg, desc, - vi->file_digest); -if (err) { -fsverity_err (inode,"Error %d computing file digest" , err); - goto fail; - } +compute_file_digest (vi->tree_params.hash_alg, desc, vi->file_digest); err =fsverity_verify_signature (vi, desc->signature,le32_to_cpu (desc->sig_size));if (err) goto fail;
fs/verity/verify.c +2 -5
@@ -5,11 +5,10 @@* Copyright 2019 Google LLC */ #include "fsverity_private.h" -#include <crypto/hash.h> #include <linux/bio.h> static struct workqueue_struct *fsverity_read_workqueue;/*
@@ -200,12 +199,11 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,struct page *hpage = hblocks[level -1 ].page;const void *haddr = hblocks[level -1 ].addr;unsigned long hblock_idx = hblocks[level -1 ].index;unsigned int hoffset = hblocks[level -1 ].hoffset; -if (fsverity_hash_block (params, inode, haddr, real_hash) !=0 ) - goto error; +fsverity_hash_block (params, inode, haddr, real_hash);if (memcmp (want_hash, real_hash, hsize) !=0 ) goto corrupted;/* * Mark the hash block as verified. This must be atomic and * idempotent, as the same hash block might be verified by
@@ -220,12 +218,11 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,kunmap_local (haddr);put_page (hpage); }/* Finally, verify the data block. */ -if (fsverity_hash_block (params, inode, data, real_hash) !=0 ) - goto error; +fsverity_hash_block (params, inode, data, real_hash);if (memcmp (want_hash, real_hash, hsize) !=0 ) goto corrupted;return true; corrupted:
Signature · 1 line
2.50.0
Quoted 8 lines · Eric Biggers
This series, including all its prerequisites, is also available at:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git fsverity-libcrypto-v1
This series makes
fs/verity/use the SHA-2 library API instead of the old-school crypto API. This is simpler and more efficient.
Quoted 8 lines
This depends on my SHA-2 library improvements for 6.17 (many patches), so this patchset might need to wait until 6.18. But I'm also thinking about just basing the fsverity tree on libcrypto-next for 6.17.
Eric Biggers (2):
lib/crypto:hash_info: Movehash_info.cintolib/crypto/
fsverity: Switch fromcrypto_shashto SHA-2 library
Quoted 18 lines
Documentation/filesystems/fsverity.rst | 3 +- crypto/Kconfig | 3 - crypto/Makefile | 1 - fs/verity/Kconfig | 6 +- fs/verity/enable.c | 8 +- fs/verity/fsverity_private.h | 24 +-- fs/verity/hash_algs.c | 194 +++++++++---------------- fs/verity/open.c | 36 ++--- fs/verity/verify.c | 7 +- lib/crypto/Kconfig | 3 + lib/crypto/Makefile | 2 + {crypto => lib/crypto}/hash_info.c | 0 12 files changed, 107 insertions(+), 180 deletions(-) rename {crypto => lib/crypto}/hash_info.c (100%)--
2.50.0
Eric Biggers
maintainerQuoted 7 lines · Eric Biggers
This series, including all its prerequisites, is also available at:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git fsverity-libcrypto-v1
This series makes
fs/verity/use the SHA-2 library API instead of the old-school crypto API. This is simpler and more efficient.
Quoted 7 lines
This depends on my SHA-2 library improvements for 6.17 (many patches), so this patchset might need to wait until 6.18. But I'm also thinking about just basing the fsverity tree on libcrypto-next for 6.17.
Eric Biggers (2):
lib/crypto:hash_info: Movehash_info.cintolib/crypto/
fsverity: Switch fromcrypto_shashto SHA-2 library
FYI, I've applied this series to
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
so that it gets linux-next coverage.
As mentioned, it depends on the SHA-256 and SHA-512 improvements in lib/crypto/. But Linus has also expressed a preference to not put too much in one pull request.
My current plan is to do 3 pull requests:
1. "Crypto library updates" - most patches, mainly SHA-256 and SHA-512 library improvements
2. "Crypto library tests" - based on (1) but adds:
lib/crypto: tests: Add hash-test-template.h and gen-hash-testvecs.py lib/crypto: tests: Add KUnit tests for SHA-224 and SHA-256 lib/crypto: tests: Add KUnit tests for SHA-384 and SHA-512 lib/crypto: tests: Add KUnit tests for Poly1305
3. "Crypto library conversions" - based on (1) but adds:
apparmor: use SHA-256 library API instead of crypto_shash API
fsverity: Explicitly include <linux/export.h>
fsverity: Switch from crypto_shash to SHA-2 library
I'll put all of these in libcrypto-next for linux-next coverage, but (3) will have a slightly different base commit in the final version.
- Eric
Eric Biggers
maintainerQuoted 35 lines · Eric Biggers
Quoted 7 lines · Eric Biggers
This series, including all its prerequisites, is also available at:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git fsverity-libcrypto-v1
This series makes
fs/verity/use the SHA-2 library API instead of the old-school crypto API. This is simpler and more efficient.Quoted 7 lines
This depends on my SHA-2 library improvements for 6.17 (many patches), so this patchset might need to wait until 6.18. But I'm also thinking about just basing the fsverity tree on libcrypto-next for 6.17.
Eric Biggers (2):
lib/crypto:hash_info: Movehash_info.cintolib/crypto/
fsverity: Switch fromcrypto_shashto SHA-2 libraryFYI, I've applied this series to
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
so that it gets linux-next coverage.As mentioned, it depends on the SHA-256 and SHA-512 improvements in
lib/crypto/. But Linus has also expressed a preference to not put too much in one pull request.My current plan is to do 3 pull requests:
1. "Crypto library updates" - most patches, mainly SHA-256 and SHA-512 library improvements
2. "Crypto library tests" - based on (1) but adds:
lib/crypto: tests: Addhash-test-template.handgen-hash-testvecs.pylib/crypto: tests: Add KUnit tests for SHA-224 and SHA-256 lib/crypto: tests: Add KUnit tests for SHA-384 and SHA-512 lib/crypto: tests: Add KUnit tests for Poly1305
Quoted 7 lines
3. "Crypto library conversions" - based on (1) but adds:
apparmor: use SHA-256 library API instead ofcrypto_shashAPI
fsverity: Explicitly include <linux/export.h>
fsverity: Switch fromcrypto_shashto SHA-2 libraryI'll put all of these in libcrypto-next for linux-next coverage, but (3) will have a slightly different base commit in the final version.
Correction: everything can have the same commit ID in libcrypto-next as in the final pull requests, if I put (2) and (3) on their own branches and merge them together. I've done that.
- Eric