Commit | Line | Data |
---|---|---|
671e67b4 EB |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
7bf765dd | 3 | * fs-verity hash algorithms |
671e67b4 EB |
4 | * |
5 | * Copyright 2019 Google LLC | |
6 | */ | |
7 | ||
8 | #include "fsverity_private.h" | |
9 | ||
10 | #include <crypto/hash.h> | |
671e67b4 EB |
11 | |
12 | /* The hash algorithms supported by fs-verity */ | |
13 | struct fsverity_hash_alg fsverity_hash_algs[] = { | |
14 | [FS_VERITY_HASH_ALG_SHA256] = { | |
15 | .name = "sha256", | |
16 | .digest_size = SHA256_DIGEST_SIZE, | |
17 | .block_size = SHA256_BLOCK_SIZE, | |
a4bbf53d | 18 | .algo_id = HASH_ALGO_SHA256, |
671e67b4 | 19 | }, |
add890c9 EB |
20 | [FS_VERITY_HASH_ALG_SHA512] = { |
21 | .name = "sha512", | |
22 | .digest_size = SHA512_DIGEST_SIZE, | |
23 | .block_size = SHA512_BLOCK_SIZE, | |
a4bbf53d | 24 | .algo_id = HASH_ALGO_SHA512, |
add890c9 | 25 | }, |
671e67b4 EB |
26 | }; |
27 | ||
439bea10 EB |
28 | static DEFINE_MUTEX(fsverity_hash_alg_init_mutex); |
29 | ||
671e67b4 EB |
30 | /** |
31 | * fsverity_get_hash_alg() - validate and prepare a hash algorithm | |
32 | * @inode: optional inode for logging purposes | |
33 | * @num: the hash algorithm number | |
34 | * | |
35 | * Get the struct fsverity_hash_alg for the given hash algorithm number, and | |
36 | * ensure it has a hash transform ready to go. The hash transforms are | |
37 | * allocated on-demand so that we don't waste resources unnecessarily, and | |
38 | * because the crypto modules may be initialized later than fs/verity/. | |
39 | * | |
40 | * Return: pointer to the hash alg on success, else an ERR_PTR() | |
41 | */ | |
32ab3c5e EB |
42 | const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode, |
43 | unsigned int num) | |
671e67b4 EB |
44 | { |
45 | struct fsverity_hash_alg *alg; | |
8fcd94ad | 46 | struct crypto_shash *tfm; |
671e67b4 EB |
47 | int err; |
48 | ||
49 | if (num >= ARRAY_SIZE(fsverity_hash_algs) || | |
50 | !fsverity_hash_algs[num].name) { | |
51 | fsverity_warn(inode, "Unknown hash algorithm number: %u", num); | |
52 | return ERR_PTR(-EINVAL); | |
53 | } | |
54 | alg = &fsverity_hash_algs[num]; | |
55 | ||
439bea10 EB |
56 | /* pairs with smp_store_release() below */ |
57 | if (likely(smp_load_acquire(&alg->tfm) != NULL)) | |
671e67b4 | 58 | return alg; |
439bea10 EB |
59 | |
60 | mutex_lock(&fsverity_hash_alg_init_mutex); | |
61 | ||
62 | if (alg->tfm != NULL) | |
63 | goto out_unlock; | |
64 | ||
8fcd94ad | 65 | tfm = crypto_alloc_shash(alg->name, 0, 0); |
671e67b4 EB |
66 | if (IS_ERR(tfm)) { |
67 | if (PTR_ERR(tfm) == -ENOENT) { | |
68 | fsverity_warn(inode, | |
69 | "Missing crypto API support for hash algorithm \"%s\"", | |
70 | alg->name); | |
439bea10 EB |
71 | alg = ERR_PTR(-ENOPKG); |
72 | goto out_unlock; | |
671e67b4 EB |
73 | } |
74 | fsverity_err(inode, | |
75 | "Error allocating hash algorithm \"%s\": %ld", | |
76 | alg->name, PTR_ERR(tfm)); | |
439bea10 EB |
77 | alg = ERR_CAST(tfm); |
78 | goto out_unlock; | |
671e67b4 EB |
79 | } |
80 | ||
81 | err = -EINVAL; | |
8fcd94ad | 82 | if (WARN_ON_ONCE(alg->digest_size != crypto_shash_digestsize(tfm))) |
671e67b4 | 83 | goto err_free_tfm; |
8fcd94ad | 84 | if (WARN_ON_ONCE(alg->block_size != crypto_shash_blocksize(tfm))) |
439bea10 EB |
85 | goto err_free_tfm; |
86 | ||
671e67b4 | 87 | pr_info("%s using implementation \"%s\"\n", |
8fcd94ad | 88 | alg->name, crypto_shash_driver_name(tfm)); |
671e67b4 | 89 | |
439bea10 EB |
90 | /* pairs with smp_load_acquire() above */ |
91 | smp_store_release(&alg->tfm, tfm); | |
92 | goto out_unlock; | |
671e67b4 EB |
93 | |
94 | err_free_tfm: | |
8fcd94ad | 95 | crypto_free_shash(tfm); |
439bea10 EB |
96 | alg = ERR_PTR(err); |
97 | out_unlock: | |
98 | mutex_unlock(&fsverity_hash_alg_init_mutex); | |
99 | return alg; | |
100 | } | |
101 | ||
671e67b4 EB |
102 | /** |
103 | * fsverity_prepare_hash_state() - precompute the initial hash state | |
104 | * @alg: hash algorithm | |
105 | * @salt: a salt which is to be prepended to all data to be hashed | |
106 | * @salt_size: salt size in bytes, possibly 0 | |
107 | * | |
108 | * Return: NULL if the salt is empty, otherwise the kmalloc()'ed precomputed | |
109 | * initial hash state on success or an ERR_PTR() on failure. | |
110 | */ | |
32ab3c5e | 111 | const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg, |
671e67b4 EB |
112 | const u8 *salt, size_t salt_size) |
113 | { | |
114 | u8 *hashstate = NULL; | |
8fcd94ad | 115 | SHASH_DESC_ON_STACK(desc, alg->tfm); |
671e67b4 EB |
116 | u8 *padded_salt = NULL; |
117 | size_t padded_salt_size; | |
671e67b4 EB |
118 | int err; |
119 | ||
8fcd94ad EB |
120 | desc->tfm = alg->tfm; |
121 | ||
671e67b4 EB |
122 | if (salt_size == 0) |
123 | return NULL; | |
124 | ||
8fcd94ad | 125 | hashstate = kmalloc(crypto_shash_statesize(alg->tfm), GFP_KERNEL); |
671e67b4 EB |
126 | if (!hashstate) |
127 | return ERR_PTR(-ENOMEM); | |
128 | ||
671e67b4 EB |
129 | /* |
130 | * Zero-pad the salt to the next multiple of the input size of the hash | |
131 | * algorithm's compression function, e.g. 64 bytes for SHA-256 or 128 | |
132 | * bytes for SHA-512. This ensures that the hash algorithm won't have | |
133 | * any bytes buffered internally after processing the salt, thus making | |
134 | * salted hashing just as fast as unsalted hashing. | |
135 | */ | |
136 | padded_salt_size = round_up(salt_size, alg->block_size); | |
137 | padded_salt = kzalloc(padded_salt_size, GFP_KERNEL); | |
138 | if (!padded_salt) { | |
139 | err = -ENOMEM; | |
140 | goto err_free; | |
141 | } | |
142 | memcpy(padded_salt, salt, salt_size); | |
8fcd94ad | 143 | err = crypto_shash_init(desc); |
671e67b4 EB |
144 | if (err) |
145 | goto err_free; | |
146 | ||
8fcd94ad | 147 | err = crypto_shash_update(desc, padded_salt, padded_salt_size); |
671e67b4 EB |
148 | if (err) |
149 | goto err_free; | |
150 | ||
8fcd94ad | 151 | err = crypto_shash_export(desc, hashstate); |
671e67b4 EB |
152 | if (err) |
153 | goto err_free; | |
154 | out: | |
671e67b4 EB |
155 | kfree(padded_salt); |
156 | return hashstate; | |
157 | ||
158 | err_free: | |
159 | kfree(hashstate); | |
160 | hashstate = ERR_PTR(err); | |
161 | goto out; | |
162 | } | |
163 | ||
164 | /** | |
f45555bf | 165 | * fsverity_hash_block() - hash a single data or hash block |
671e67b4 EB |
166 | * @params: the Merkle tree's parameters |
167 | * @inode: inode for which the hashing is being done | |
8fcd94ad | 168 | * @data: virtual address of a buffer containing the block to hash |
671e67b4 EB |
169 | * @out: output digest, size 'params->digest_size' bytes |
170 | * | |
f45555bf EB |
171 | * Hash a single data or hash block. The hash is salted if a salt is specified |
172 | * in the Merkle tree parameters. | |
671e67b4 EB |
173 | * |
174 | * Return: 0 on success, -errno on failure | |
175 | */ | |
f45555bf | 176 | int fsverity_hash_block(const struct merkle_tree_params *params, |
8fcd94ad | 177 | const struct inode *inode, const void *data, u8 *out) |
671e67b4 | 178 | { |
8fcd94ad | 179 | SHASH_DESC_ON_STACK(desc, params->hash_alg->tfm); |
671e67b4 EB |
180 | int err; |
181 | ||
8fcd94ad | 182 | desc->tfm = params->hash_alg->tfm; |
671e67b4 EB |
183 | |
184 | if (params->hashstate) { | |
8fcd94ad | 185 | err = crypto_shash_import(desc, params->hashstate); |
671e67b4 EB |
186 | if (err) { |
187 | fsverity_err(inode, | |
188 | "Error %d importing hash state", err); | |
189 | return err; | |
190 | } | |
8fcd94ad | 191 | err = crypto_shash_finup(desc, data, params->block_size, out); |
671e67b4 | 192 | } else { |
8fcd94ad | 193 | err = crypto_shash_digest(desc, data, params->block_size, out); |
671e67b4 | 194 | } |
671e67b4 | 195 | if (err) |
f45555bf | 196 | fsverity_err(inode, "Error %d computing block hash", err); |
671e67b4 EB |
197 | return err; |
198 | } | |
199 | ||
200 | /** | |
201 | * fsverity_hash_buffer() - hash some data | |
202 | * @alg: the hash algorithm to use | |
203 | * @data: the data to hash | |
204 | * @size: size of data to hash, in bytes | |
205 | * @out: output digest, size 'alg->digest_size' bytes | |
206 | * | |
671e67b4 EB |
207 | * Return: 0 on success, -errno on failure |
208 | */ | |
32ab3c5e | 209 | int fsverity_hash_buffer(const struct fsverity_hash_alg *alg, |
671e67b4 EB |
210 | const void *data, size_t size, u8 *out) |
211 | { | |
8fcd94ad | 212 | return crypto_shash_tfm_digest(alg->tfm, data, size, out); |
671e67b4 EB |
213 | } |
214 | ||
215 | void __init fsverity_check_hash_algs(void) | |
216 | { | |
217 | size_t i; | |
218 | ||
219 | /* | |
220 | * Sanity check the hash algorithms (could be a build-time check, but | |
221 | * they're in an array) | |
222 | */ | |
223 | for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) { | |
224 | const struct fsverity_hash_alg *alg = &fsverity_hash_algs[i]; | |
225 | ||
226 | if (!alg->name) | |
227 | continue; | |
228 | ||
5d37a119 EB |
229 | /* |
230 | * 0 must never be allocated as an FS_VERITY_HASH_ALG_* value, | |
231 | * as it is reserved for users that use 0 to mean unspecified or | |
232 | * a default value. fs/verity/ itself doesn't care and doesn't | |
233 | * have a default algorithm, but some users make use of this. | |
234 | */ | |
235 | BUG_ON(i == 0); | |
236 | ||
671e67b4 EB |
237 | BUG_ON(alg->digest_size > FS_VERITY_MAX_DIGEST_SIZE); |
238 | ||
239 | /* | |
240 | * For efficiency, the implementation currently assumes the | |
241 | * digest and block sizes are powers of 2. This limitation can | |
242 | * be lifted if the code is updated to handle other values. | |
243 | */ | |
244 | BUG_ON(!is_power_of_2(alg->digest_size)); | |
245 | BUG_ON(!is_power_of_2(alg->block_size)); | |
a4bbf53d EB |
246 | |
247 | /* Verify that there is a valid mapping to HASH_ALGO_*. */ | |
248 | BUG_ON(alg->algo_id == 0); | |
249 | BUG_ON(alg->digest_size != hash_digest_size[alg->algo_id]); | |
671e67b4 EB |
250 | } |
251 | } |