432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 1) // SPDX-License-Identifier: GPL-2.0
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 2) /*
7bf765dd8442d (Eric Biggers 2020-11-13 13:19:15 -0800 3) * Verification of builtin signatures
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 4) *
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 5) * Copyright 2019 Google LLC
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 6) */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 7)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 8) #include "fsverity_private.h"
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 9)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 10) #include <linux/cred.h>
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 11) #include <linux/key.h>
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 12) #include <linux/slab.h>
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 13) #include <linux/verification.h>
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 14)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 15) /*
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 16) * /proc/sys/fs/verity/require_signatures
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 17) * If 1, all verity files must have a valid builtin signature.
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 18) */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 19) static int fsverity_require_signatures;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 20)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 21) /*
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 22) * Keyring that contains the trusted X.509 certificates.
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 23) *
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 24) * Only root (kuid=0) can modify this. Also, root may use
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 25) * keyctl_restrict_keyring() to prevent any more additions.
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 26) */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 27) static struct key *fsverity_keyring;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 28)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 29) /**
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 30) * fsverity_verify_signature() - check a verity file's signature
6377a38bd345b (Eric Biggers 2020-05-11 12:21:17 -0700 31) * @vi: the file's fsverity_info
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 32) * @signature: the file's built-in signature
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 33) * @sig_size: size of signature in bytes, or 0 if no signature
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 34) *
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 35) * If the file includes a signature of its fs-verity file digest, verify it
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 36) * against the certificates in the fs-verity keyring.
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 37) *
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 38) * Return: 0 on success (signature valid or not required); -errno on failure
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 39) */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 40) int fsverity_verify_signature(const struct fsverity_info *vi,
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 41) const u8 *signature, size_t sig_size)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 42) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 43) const struct inode *inode = vi->inode;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 44) const struct fsverity_hash_alg *hash_alg = vi->tree_params.hash_alg;
9e90f30e78572 (Eric Biggers 2020-11-13 13:19:16 -0800 45) struct fsverity_formatted_digest *d;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 46) int err;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 47)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 48) if (sig_size == 0) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 49) if (fsverity_require_signatures) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 50) fsverity_err(inode,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 51) "require_signatures=1, rejecting unsigned file!");
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 52) return -EPERM;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 53) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 54) return 0;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 55) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 56)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 57) d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 58) if (!d)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 59) return -ENOMEM;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 60) memcpy(d->magic, "FSVerity", 8);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 61) d->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 62) d->digest_size = cpu_to_le16(hash_alg->digest_size);
ed45e20164934 (Eric Biggers 2020-11-13 13:19:17 -0800 63) memcpy(d->digest, vi->file_digest, hash_alg->digest_size);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 64)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 65) err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size,
fab634c4de460 (Eric Biggers 2021-01-15 10:18:15 -0800 66) signature, sig_size, fsverity_keyring,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 67) VERIFYING_UNSPECIFIED_SIGNATURE,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 68) NULL, NULL);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 69) kfree(d);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 70)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 71) if (err) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 72) if (err == -ENOKEY)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 73) fsverity_err(inode,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 74) "File's signing cert isn't in the fs-verity keyring");
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 75) else if (err == -EKEYREJECTED)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 76) fsverity_err(inode, "Incorrect file signature");
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 77) else if (err == -EBADMSG)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 78) fsverity_err(inode, "Malformed file signature");
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 79) else
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 80) fsverity_err(inode, "Error %d verifying file signature",
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 81) err);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 82) return err;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 83) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 84)
ed45e20164934 (Eric Biggers 2020-11-13 13:19:17 -0800 85) pr_debug("Valid signature for file digest %s:%*phN\n",
ed45e20164934 (Eric Biggers 2020-11-13 13:19:17 -0800 86) hash_alg->name, hash_alg->digest_size, vi->file_digest);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 87) return 0;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 88) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 89)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 90) #ifdef CONFIG_SYSCTL
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 91) static struct ctl_table_header *fsverity_sysctl_header;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 92)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 93) static const struct ctl_path fsverity_sysctl_path[] = {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 94) { .procname = "fs", },
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 95) { .procname = "verity", },
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 96) { }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 97) };
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 98)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 99) static struct ctl_table fsverity_sysctl_table[] = {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 100) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 101) .procname = "require_signatures",
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 102) .data = &fsverity_require_signatures,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 103) .maxlen = sizeof(int),
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 104) .mode = 0644,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 105) .proc_handler = proc_dointvec_minmax,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 106) .extra1 = SYSCTL_ZERO,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 107) .extra2 = SYSCTL_ONE,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 108) },
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 109) { }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 110) };
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 111)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 112) static int __init fsverity_sysctl_init(void)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 113) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 114) fsverity_sysctl_header = register_sysctl_paths(fsverity_sysctl_path,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 115) fsverity_sysctl_table);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 116) if (!fsverity_sysctl_header) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 117) pr_err("sysctl registration failed!\n");
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 118) return -ENOMEM;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 119) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 120) return 0;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 121) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 122) #else /* !CONFIG_SYSCTL */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 123) static inline int __init fsverity_sysctl_init(void)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 124) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 125) return 0;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 126) }
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 127) #endif /* !CONFIG_SYSCTL */
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 128)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 129) int __init fsverity_init_signature(void)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 130) {
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 131) struct key *ring;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 132) int err;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 133)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 134) ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 135) current_cred(), KEY_POS_SEARCH |
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 136) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE |
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 137) KEY_USR_SEARCH | KEY_USR_SETATTR,
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 138) KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 139) if (IS_ERR(ring))
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 140) return PTR_ERR(ring);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 141)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 142) err = fsverity_sysctl_init();
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 143) if (err)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 144) goto err_put_ring;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 145)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 146) fsverity_keyring = ring;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 147) return 0;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 148)
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 149) err_put_ring:
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 150) key_put(ring);
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 151) return err;
432434c9f8e18 (Eric Biggers 2019-07-22 09:26:23 -0700 152) }