OSDN Git Service

fs-verity: define a function to return the integrity protected file digest
authorMimi Zohar <zohar@linux.ibm.com>
Tue, 23 Nov 2021 18:37:52 +0000 (13:37 -0500)
committerMimi Zohar <zohar@linux.ibm.com>
Sun, 1 May 2022 20:39:36 +0000 (16:39 -0400)
Define a function named fsverity_get_digest() to return the verity file
digest and the associated hash algorithm (enum hash_algo).

This assumes that before calling fsverity_get_digest() the file must have
been opened, which is even true for the IMA measure/appraise on file
open policy rule use case (func=FILE_CHECK).  do_open() calls vfs_open()
immediately prior to ima_file_check().

Acked-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
fs/verity/Kconfig
fs/verity/fsverity_private.h
fs/verity/measure.c
include/linux/fsverity.h

index 24d1b54..54598cd 100644 (file)
@@ -3,6 +3,7 @@
 config FS_VERITY
        bool "FS Verity (read-only file-based authenticity protection)"
        select CRYPTO
+       select CRYPTO_HASH_INFO
        # SHA-256 is implied as it's intended to be the default hash algorithm.
        # To avoid bloat, other wanted algorithms must be selected explicitly.
        # Note that CRYPTO_SHA256 denotes the generic C implementation, but
index a792043..c6fb62e 100644 (file)
@@ -14,7 +14,6 @@
 
 #define pr_fmt(fmt) "fs-verity: " fmt
 
-#include <crypto/sha2.h>
 #include <linux/fsverity.h>
 #include <linux/mempool.h>
 
@@ -26,12 +25,6 @@ struct ahash_request;
  */
 #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      SHA512_DIGEST_SIZE
-
 /* A hash algorithm supported by fs-verity */
 struct fsverity_hash_alg {
        struct crypto_ahash *tfm; /* hash tfm, allocated on demand */
index f0d7b30..e99c003 100644 (file)
@@ -57,3 +57,46 @@ int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
        return 0;
 }
 EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);
+
+/**
+ * fsverity_get_digest() - get a verity file's digest
+ * @inode: inode to get digest of
+ * @digest: (out) pointer to the digest
+ * @alg: (out) pointer to the hash algorithm enumeration
+ *
+ * Return the file hash algorithm and digest of an fsverity protected file.
+ * Assumption: before calling fsverity_get_digest(), the file must have been
+ * opened.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int fsverity_get_digest(struct inode *inode,
+                       u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
+                       enum hash_algo *alg)
+{
+       const struct fsverity_info *vi;
+       const struct fsverity_hash_alg *hash_alg;
+       int i;
+
+       vi = fsverity_get_info(inode);
+       if (!vi)
+               return -ENODATA; /* not a verity file */
+
+       hash_alg = vi->tree_params.hash_alg;
+       memset(digest, 0, FS_VERITY_MAX_DIGEST_SIZE);
+
+       /* convert the verity hash algorithm name to a hash_algo_name enum */
+       i = match_string(hash_algo_name, HASH_ALGO__LAST, hash_alg->name);
+       if (i < 0)
+               return -EINVAL;
+       *alg = i;
+
+       if (WARN_ON_ONCE(hash_alg->digest_size != hash_digest_size[*alg]))
+               return -EINVAL;
+       memcpy(digest, vi->file_digest, hash_alg->digest_size);
+
+       pr_debug("file digest %s:%*phN\n", hash_algo_name[*alg],
+                hash_digest_size[*alg], digest);
+
+       return 0;
+}
index a7afc80..7af030f 100644 (file)
 #define _LINUX_FSVERITY_H
 
 #include <linux/fs.h>
+#include <crypto/hash_info.h>
+#include <crypto/sha2.h>
 #include <uapi/linux/fsverity.h>
 
+/*
+ * 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      SHA512_DIGEST_SIZE
+
 /* Verity operations for filesystems */
 struct fsverity_operations {
 
@@ -131,6 +139,9 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
 /* measure.c */
 
 int fsverity_ioctl_measure(struct file *filp, void __user *arg);
+int fsverity_get_digest(struct inode *inode,
+                       u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
+                       enum hash_algo *alg);
 
 /* open.c */
 
@@ -170,6 +181,13 @@ static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg)
        return -EOPNOTSUPP;
 }
 
+static inline int fsverity_get_digest(struct inode *inode,
+                                     u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
+                                     enum hash_algo *alg)
+{
+       return -EOPNOTSUPP;
+}
+
 /* open.c */
 
 static inline int fsverity_file_open(struct inode *inode, struct file *filp)