| .. | .. |
|---|
| 27 | 27 | static struct key *fsverity_keyring; |
|---|
| 28 | 28 | |
|---|
| 29 | 29 | /** |
|---|
| 30 | + * fsverity_verify_signature() - check a verity file's signature |
|---|
| 31 | + * @vi: the file's fsverity_info |
|---|
| 32 | + * @signature: the file's built-in signature |
|---|
| 33 | + * @sig_size: size of signature in bytes, or 0 if no signature |
|---|
| 34 | + * |
|---|
| 35 | + * If the file includes a signature of its fs-verity file digest, verify it |
|---|
| 36 | + * against the certificates in the fs-verity keyring. |
|---|
| 37 | + * |
|---|
| 38 | + * Return: 0 on success (signature valid or not required); -errno on failure |
|---|
| 39 | + */ |
|---|
| 40 | +int fsverity_verify_signature(const struct fsverity_info *vi, |
|---|
| 41 | + const u8 *signature, size_t sig_size) |
|---|
| 42 | +{ |
|---|
| 43 | + unsigned int digest_algorithm = |
|---|
| 44 | + vi->tree_params.hash_alg - fsverity_hash_algs; |
|---|
| 45 | + |
|---|
| 46 | + return __fsverity_verify_signature(vi->inode, signature, sig_size, |
|---|
| 47 | + vi->file_digest, digest_algorithm); |
|---|
| 48 | +} |
|---|
| 49 | + |
|---|
| 50 | +/** |
|---|
| 30 | 51 | * __fsverity_verify_signature() - check a verity file's signature |
|---|
| 31 | 52 | * @inode: the file's inode |
|---|
| 32 | 53 | * @signature: the file's signature |
|---|
| .. | .. |
|---|
| 40 | 61 | * Return: 0 on success (signature valid or not required); -errno on failure |
|---|
| 41 | 62 | */ |
|---|
| 42 | 63 | int __fsverity_verify_signature(const struct inode *inode, const u8 *signature, |
|---|
| 43 | | - u32 sig_size, const u8 *file_digest, |
|---|
| 64 | + size_t sig_size, const u8 *file_digest, |
|---|
| 44 | 65 | unsigned int digest_algorithm) |
|---|
| 45 | 66 | { |
|---|
| 46 | 67 | struct fsverity_formatted_digest *d; |
|---|
| .. | .. |
|---|
| 60 | 81 | return 0; |
|---|
| 61 | 82 | } |
|---|
| 62 | 83 | |
|---|
| 84 | + if (fsverity_keyring->keys.nr_leaves_on_tree == 0) { |
|---|
| 85 | + /* |
|---|
| 86 | + * The ".fs-verity" keyring is empty, due to builtin signatures |
|---|
| 87 | + * being supported by the kernel but not actually being used. |
|---|
| 88 | + * In this case, verify_pkcs7_signature() would always return an |
|---|
| 89 | + * error, usually ENOKEY. It could also be EBADMSG if the |
|---|
| 90 | + * PKCS#7 is malformed, but that isn't very important to |
|---|
| 91 | + * distinguish. So, just skip to ENOKEY to avoid the attack |
|---|
| 92 | + * surface of the PKCS#7 parser, which would otherwise be |
|---|
| 93 | + * reachable by any task able to execute FS_IOC_ENABLE_VERITY. |
|---|
| 94 | + */ |
|---|
| 95 | + fsverity_err(inode, |
|---|
| 96 | + "fs-verity keyring is empty, rejecting signed file!"); |
|---|
| 97 | + return -ENOKEY; |
|---|
| 98 | + } |
|---|
| 99 | + |
|---|
| 63 | 100 | d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL); |
|---|
| 64 | 101 | if (!d) |
|---|
| 65 | 102 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 69 | 106 | memcpy(d->digest, file_digest, hash_alg->digest_size); |
|---|
| 70 | 107 | |
|---|
| 71 | 108 | err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size, |
|---|
| 72 | | - signature, sig_size, |
|---|
| 73 | | - fsverity_keyring, |
|---|
| 109 | + signature, sig_size, fsverity_keyring, |
|---|
| 74 | 110 | VERIFYING_UNSPECIFIED_SIGNATURE, |
|---|
| 75 | 111 | NULL, NULL); |
|---|
| 76 | 112 | kfree(d); |
|---|
| .. | .. |
|---|
| 95 | 131 | } |
|---|
| 96 | 132 | EXPORT_SYMBOL_GPL(__fsverity_verify_signature); |
|---|
| 97 | 133 | |
|---|
| 98 | | -/** |
|---|
| 99 | | - * fsverity_verify_signature() - check a verity file's signature |
|---|
| 100 | | - * @vi: the file's fsverity_info |
|---|
| 101 | | - * @desc: the file's fsverity_descriptor |
|---|
| 102 | | - * @desc_size: size of @desc |
|---|
| 103 | | - * |
|---|
| 104 | | - * If the file's fs-verity descriptor includes a signature of the file digest, |
|---|
| 105 | | - * verify it against the certificates in the fs-verity keyring. |
|---|
| 106 | | - * |
|---|
| 107 | | - * Return: 0 on success (signature valid or not required); -errno on failure |
|---|
| 108 | | - */ |
|---|
| 109 | | -int fsverity_verify_signature(const struct fsverity_info *vi, |
|---|
| 110 | | - const struct fsverity_descriptor *desc, |
|---|
| 111 | | - size_t desc_size) |
|---|
| 112 | | -{ |
|---|
| 113 | | - const struct inode *inode = vi->inode; |
|---|
| 114 | | - const struct fsverity_hash_alg *hash_alg = vi->tree_params.hash_alg; |
|---|
| 115 | | - const u32 sig_size = le32_to_cpu(desc->sig_size); |
|---|
| 116 | | - |
|---|
| 117 | | - if (sig_size > desc_size - sizeof(*desc)) { |
|---|
| 118 | | - fsverity_err(inode, "Signature overflows verity descriptor"); |
|---|
| 119 | | - return -EBADMSG; |
|---|
| 120 | | - } |
|---|
| 121 | | - |
|---|
| 122 | | - return __fsverity_verify_signature(inode, desc->signature, sig_size, |
|---|
| 123 | | - vi->file_digest, hash_alg - fsverity_hash_algs); |
|---|
| 124 | | -} |
|---|
| 125 | | - |
|---|
| 126 | 134 | #ifdef CONFIG_SYSCTL |
|---|
| 127 | 135 | static struct ctl_table_header *fsverity_sysctl_header; |
|---|
| 128 | 136 | |
|---|
| .. | .. |
|---|
| 131 | 139 | { .procname = "verity", }, |
|---|
| 132 | 140 | { } |
|---|
| 133 | 141 | }; |
|---|
| 134 | | - |
|---|
| 135 | | -/* shared constants to be used in various sysctls */ |
|---|
| 136 | | -static int sysctl_vals[] = { 0, 1, INT_MAX }; |
|---|
| 137 | | - |
|---|
| 138 | | -#define SYSCTL_ZERO ((void *)&sysctl_vals[0]) |
|---|
| 139 | | -#define SYSCTL_ONE ((void *)&sysctl_vals[1]) |
|---|
| 140 | | -#define SYSCTL_INT_MAX ((void *)&sysctl_vals[2]) |
|---|
| 141 | 142 | |
|---|
| 142 | 143 | static struct ctl_table fsverity_sysctl_table[] = { |
|---|
| 143 | 144 | { |
|---|