.. | .. |
---|
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 | { |
---|