android_kernel_xiaomi_sm7250/fs/verity/signature.c

188 lines
5.0 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: GPL-2.0
/*
* Verification of builtin signatures
*
* Copyright 2019 Google LLC
*/
#include "fsverity_private.h"
#include <linux/cred.h>
#include <linux/key.h>
#include <linux/slab.h>
#include <linux/verification.h>
/*
* /proc/sys/fs/verity/require_signatures
* If 1, all verity files must have a valid builtin signature.
*/
static int fsverity_require_signatures;
/*
* Keyring that contains the trusted X.509 certificates.
*
* Only root (kuid=0) can modify this. Also, root may use
* keyctl_restrict_keyring() to prevent any more additions.
*/
static struct key *fsverity_keyring;
/**
* fsverity_verify_signature() - check a verity file's signature
* @vi: the file's fsverity_info
* @signature: the file's built-in signature
* @sig_size: size of signature in bytes, or 0 if no signature
*
* If the file includes a signature of its fs-verity file digest, verify it
* against the certificates in the fs-verity keyring.
*
* Return: 0 on success (signature valid or not required); -errno on failure
*/
int fsverity_verify_signature(const struct fsverity_info *vi,
const u8 *signature, size_t sig_size)
{
Merge tag '5.12-rc1-4.19' of https://kernel.googlesource.com/pub/scm/linux/kernel/git/jaegeuk/f2fs-stable into HEAD * tag '5.12-rc1-4.19' of https://kernel.googlesource.com/pub/scm/linux/kernel/git/jaegeuk/f2fs-stable: fs-verity: support reading signature with ioctl fs-verity: support reading descriptor with ioctl fs-verity: support reading Merkle tree with ioctl fs-verity: add FS_IOC_READ_VERITY_METADATA ioctl fs-verity: don't pass whole descriptor to fsverity_verify_signature() fs-verity: factor out fsverity_get_descriptor() f2fs: remove FAULT_ALLOC_BIO f2fs: use blkdev_issue_flush in __submit_flush_wait f2fs: remove a few bd_part checks fs-verity: move structs needed for file signing to UAPI header fs-verity: rename "file measurement" to "file digest" fs-verity: rename fsverity_signed_digest to fsverity_formatted_digest fs-verity: remove filenames from file comments fs-verity: use smp_load_acquire() for ->i_verity_info Documentation: f2fs: fix typo s/automaic/automatic f2fs: give a warning only for readonly partition f2fs: don't grab superblock freeze for flush/ckpt thread f2fs: add ckpt_thread_ioprio sysfs node f2fs: introduce checkpoint_merge mount option f2fs: relocate inline conversion from mmap() to mkwrite() f2fs: fix a wrong condition in __submit_bio f2fs: remove unnecessary initialization in xattr.c f2fs: fix to avoid inconsistent quota data f2fs: flush data when enabling checkpoint back f2fs: deprecate f2fs_trace_io f2fs: remove unused stat_{inc, dec}_atomic_write f2fs: introduce sb_status sysfs node f2fs: fix to use per-inode maxbytes f2fs: compress: fix potential deadlock libfs: unexport generic_ci_d_compare() and generic_ci_d_hash() f2fs: fix to set/clear I_LINKABLE under i_lock f2fs: fix null page reference in redirty_blocks f2fs: clean up post-read processing f2fs: trival cleanup in move_data_block() f2fs: fix out-of-repair __setattr_copy() f2fs: fix to tag FIEMAP_EXTENT_MERGED in f2fs_fiemap() f2fs: introduce a new per-sb directory in sysfs f2fs: compress: support compress level f2fs: compress: deny setting unsupported compress algorithm f2fs: relocate f2fs_precache_extents() f2fs: enforce the immutable flag on open files f2fs: enhance to update i_mode and acl atomically in f2fs_setattr() f2fs: fix to set inode->i_mode correctly for posix_acl_update_mode f2fs: Replace expression with offsetof() f2fs: handle unallocated section and zone on pinned/atgc Change-Id: I88c2467fb263f9ddfda6eda8ba16037c433db8f2 Signed-off-by: UtsavBalar1231 <utsavbalar1231@gmail.com> Conflicts: fs/ext4/ioctl.c fs/f2fs/data.c fs/f2fs/file.c fs/verity/signature.c include/uapi/linux/fsverity.h
2022-07-03 16:22:19 +02:00
unsigned int digest_algorithm =
vi->tree_params.hash_alg - fsverity_hash_algs;
return __fsverity_verify_signature(vi->inode, signature, sig_size,
vi->file_digest, digest_algorithm);
}
/**
* __fsverity_verify_signature() - check a verity file's signature
* @inode: the file's inode
* @signature: the file's signature
* @sig_size: size of @signature. Can be 0 if there is no signature
* @file_digest: the file's digest
* @digest_algorithm: the digest algorithm used
*
* Takes the file's digest and optional signature and verifies the signature
* against the digest and the fs-verity keyring if appropriate
*
* Return: 0 on success (signature valid or not required); -errno on failure
*/
int __fsverity_verify_signature(const struct inode *inode, const u8 *signature,
u32 sig_size, const u8 *file_digest,
unsigned int digest_algorithm)
{
struct fsverity_formatted_digest *d;
struct fsverity_hash_alg *hash_alg = fsverity_get_hash_alg(inode,
digest_algorithm);
int err;
if (IS_ERR(hash_alg))
return PTR_ERR(hash_alg);
if (sig_size == 0) {
if (fsverity_require_signatures) {
fsverity_err(inode,
"require_signatures=1, rejecting unsigned file!");
return -EPERM;
}
return 0;
}
d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
if (!d)
return -ENOMEM;
memcpy(d->magic, "FSVerity", 8);
d->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
d->digest_size = cpu_to_le16(hash_alg->digest_size);
memcpy(d->digest, file_digest, hash_alg->digest_size);
err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size,
signature, sig_size, fsverity_keyring,
VERIFYING_UNSPECIFIED_SIGNATURE,
NULL, NULL);
kfree(d);
if (err) {
if (err == -ENOKEY)
fsverity_err(inode,
"File's signing cert isn't in the fs-verity keyring");
else if (err == -EKEYREJECTED)
fsverity_err(inode, "Incorrect file signature");
else if (err == -EBADMSG)
fsverity_err(inode, "Malformed file signature");
else
fsverity_err(inode, "Error %d verifying file signature",
err);
return err;
}
UPSTREAM: fs-verity: rename "file measurement" to "file digest" I originally chose the name "file measurement" to refer to the fs-verity file digest to avoid confusion with traditional full-file digests or with the bare root hash of the Merkle tree. But the name "file measurement" hasn't caught on, and usually people are calling it something else, usually the "file digest". E.g. see "struct fsverity_digest" and "struct fsverity_formatted_digest", the libfsverity_compute_digest() and libfsverity_sign_digest() functions in libfsverity, and the "fsverity digest" command. Having multiple names for the same thing is always confusing. So to hopefully avoid confusion in the future, rename "fs-verity file measurement" to "fs-verity file digest". This leaves FS_IOC_MEASURE_VERITY as the only reference to "measure" in the kernel, which makes some amount of sense since the ioctl is actively "measuring" the file. I'll be renaming this in fsverity-utils too (though similarly the 'fsverity measure' command, which is a wrapper for FS_IOC_MEASURE_VERITY, will stay). Acked-by: Luca Boccassi <luca.boccassi@microsoft.com> Link: https://lore.kernel.org/r/20201113211918.71883-4-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com> Bug: 186190934 Test: With rest of series and ABI update incrementalfs.ko loads (cherry picked from commit ed45e201649344412445d6f65f0473a6112f0bcd) Signed-off-by: Paul Lawrence <paullawrence@google.com> Change-Id: I200ed0cc32b0aeabdc7f17e4b804b52b3c594c2d
2020-11-13 22:19:17 +01:00
pr_debug("Valid signature for file digest %s:%*phN\n",
hash_alg->name, hash_alg->digest_size, file_digest);
return 0;
}
EXPORT_SYMBOL_GPL(__fsverity_verify_signature);
#ifdef CONFIG_SYSCTL
static struct ctl_table_header *fsverity_sysctl_header;
static const struct ctl_path fsverity_sysctl_path[] = {
{ .procname = "fs", },
{ .procname = "verity", },
{ }
};
/* shared constants to be used in various sysctls */
static int sysctl_vals[] = { 0, 1, INT_MAX };
#define SYSCTL_ZERO ((void *)&sysctl_vals[0])
#define SYSCTL_ONE ((void *)&sysctl_vals[1])
#define SYSCTL_INT_MAX ((void *)&sysctl_vals[2])
static struct ctl_table fsverity_sysctl_table[] = {
{
.procname = "require_signatures",
.data = &fsverity_require_signatures,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{ }
};
static int __init fsverity_sysctl_init(void)
{
fsverity_sysctl_header = register_sysctl_paths(fsverity_sysctl_path,
fsverity_sysctl_table);
if (!fsverity_sysctl_header) {
pr_err("sysctl registration failed!\n");
return -ENOMEM;
}
return 0;
}
#else /* !CONFIG_SYSCTL */
static inline int __init fsverity_sysctl_init(void)
{
return 0;
}
#endif /* !CONFIG_SYSCTL */
int __init fsverity_init_signature(void)
{
struct key *ring;
int err;
ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
current_cred(), KEY_POS_SEARCH |
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE |
KEY_USR_SEARCH | KEY_USR_SETATTR,
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
if (IS_ERR(ring))
return PTR_ERR(ring);
err = fsverity_sysctl_init();
if (err)
goto err_put_ring;
fsverity_keyring = ring;
return 0;
err_put_ring:
key_put(ring);
return err;
}