xref: /linux/fs/ubifs/auth.c (revision 44f57d78)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * This file is part of UBIFS.
4  *
5  * Copyright (C) 2018 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
6  */
7 
8 /*
9  * This file implements various helper functions for UBIFS authentication support
10  */
11 
12 #include <linux/crypto.h>
13 #include <crypto/hash.h>
14 #include <crypto/sha.h>
15 #include <crypto/algapi.h>
16 #include <keys/user-type.h>
17 
18 #include "ubifs.h"
19 
20 /**
21  * ubifs_node_calc_hash - calculate the hash of a UBIFS node
22  * @c: UBIFS file-system description object
23  * @node: the node to calculate a hash for
24  * @hash: the returned hash
25  *
26  * Returns 0 for success or a negative error code otherwise.
27  */
28 int __ubifs_node_calc_hash(const struct ubifs_info *c, const void *node,
29 			    u8 *hash)
30 {
31 	const struct ubifs_ch *ch = node;
32 	SHASH_DESC_ON_STACK(shash, c->hash_tfm);
33 	int err;
34 
35 	shash->tfm = c->hash_tfm;
36 
37 	err = crypto_shash_digest(shash, node, le32_to_cpu(ch->len), hash);
38 	if (err < 0)
39 		return err;
40 	return 0;
41 }
42 
43 /**
44  * ubifs_hash_calc_hmac - calculate a HMAC from a hash
45  * @c: UBIFS file-system description object
46  * @hash: the node to calculate a HMAC for
47  * @hmac: the returned HMAC
48  *
49  * Returns 0 for success or a negative error code otherwise.
50  */
51 static int ubifs_hash_calc_hmac(const struct ubifs_info *c, const u8 *hash,
52 				 u8 *hmac)
53 {
54 	SHASH_DESC_ON_STACK(shash, c->hmac_tfm);
55 	int err;
56 
57 	shash->tfm = c->hmac_tfm;
58 
59 	err = crypto_shash_digest(shash, hash, c->hash_len, hmac);
60 	if (err < 0)
61 		return err;
62 	return 0;
63 }
64 
65 /**
66  * ubifs_prepare_auth_node - Prepare an authentication node
67  * @c: UBIFS file-system description object
68  * @node: the node to calculate a hash for
69  * @hash: input hash of previous nodes
70  *
71  * This function prepares an authentication node for writing onto flash.
72  * It creates a HMAC from the given input hash and writes it to the node.
73  *
74  * Returns 0 for success or a negative error code otherwise.
75  */
76 int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
77 			     struct shash_desc *inhash)
78 {
79 	struct ubifs_auth_node *auth = node;
80 	u8 *hash;
81 	int err;
82 
83 	hash = kmalloc(crypto_shash_descsize(c->hash_tfm), GFP_NOFS);
84 	if (!hash)
85 		return -ENOMEM;
86 
87 	{
88 		SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
89 
90 		hash_desc->tfm = c->hash_tfm;
91 		ubifs_shash_copy_state(c, inhash, hash_desc);
92 
93 		err = crypto_shash_final(hash_desc, hash);
94 		if (err)
95 			goto out;
96 	}
97 
98 	err = ubifs_hash_calc_hmac(c, hash, auth->hmac);
99 	if (err)
100 		goto out;
101 
102 	auth->ch.node_type = UBIFS_AUTH_NODE;
103 	ubifs_prepare_node(c, auth, ubifs_auth_node_sz(c), 0);
104 
105 	err = 0;
106 out:
107 	kfree(hash);
108 
109 	return err;
110 }
111 
112 static struct shash_desc *ubifs_get_desc(const struct ubifs_info *c,
113 					 struct crypto_shash *tfm)
114 {
115 	struct shash_desc *desc;
116 	int err;
117 
118 	if (!ubifs_authenticated(c))
119 		return NULL;
120 
121 	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
122 	if (!desc)
123 		return ERR_PTR(-ENOMEM);
124 
125 	desc->tfm = tfm;
126 
127 	err = crypto_shash_init(desc);
128 	if (err) {
129 		kfree(desc);
130 		return ERR_PTR(err);
131 	}
132 
133 	return desc;
134 }
135 
136 /**
137  * __ubifs_hash_get_desc - get a descriptor suitable for hashing a node
138  * @c: UBIFS file-system description object
139  *
140  * This function returns a descriptor suitable for hashing a node. Free after use
141  * with kfree.
142  */
143 struct shash_desc *__ubifs_hash_get_desc(const struct ubifs_info *c)
144 {
145 	return ubifs_get_desc(c, c->hash_tfm);
146 }
147 
148 /**
149  * ubifs_bad_hash - Report hash mismatches
150  * @c: UBIFS file-system description object
151  * @node: the node
152  * @hash: the expected hash
153  * @lnum: the LEB @node was read from
154  * @offs: offset in LEB @node was read from
155  *
156  * This function reports a hash mismatch when a node has a different hash than
157  * expected.
158  */
159 void ubifs_bad_hash(const struct ubifs_info *c, const void *node, const u8 *hash,
160 		    int lnum, int offs)
161 {
162 	int len = min(c->hash_len, 20);
163 	int cropped = len != c->hash_len;
164 	const char *cont = cropped ? "..." : "";
165 
166 	u8 calc[UBIFS_HASH_ARR_SZ];
167 
168 	__ubifs_node_calc_hash(c, node, calc);
169 
170 	ubifs_err(c, "hash mismatch on node at LEB %d:%d", lnum, offs);
171 	ubifs_err(c, "hash expected:   %*ph%s", len, hash, cont);
172 	ubifs_err(c, "hash calculated: %*ph%s", len, calc, cont);
173 }
174 
175 /**
176  * __ubifs_node_check_hash - check the hash of a node against given hash
177  * @c: UBIFS file-system description object
178  * @node: the node
179  * @expected: the expected hash
180  *
181  * This function calculates a hash over a node and compares it to the given hash.
182  * Returns 0 if both hashes are equal or authentication is disabled, otherwise a
183  * negative error code is returned.
184  */
185 int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node,
186 			    const u8 *expected)
187 {
188 	u8 calc[UBIFS_HASH_ARR_SZ];
189 	int err;
190 
191 	err = __ubifs_node_calc_hash(c, node, calc);
192 	if (err)
193 		return err;
194 
195 	if (ubifs_check_hash(c, expected, calc))
196 		return -EPERM;
197 
198 	return 0;
199 }
200 
201 /**
202  * ubifs_init_authentication - initialize UBIFS authentication support
203  * @c: UBIFS file-system description object
204  *
205  * This function returns 0 for success or a negative error code otherwise.
206  */
207 int ubifs_init_authentication(struct ubifs_info *c)
208 {
209 	struct key *keyring_key;
210 	const struct user_key_payload *ukp;
211 	int err;
212 	char hmac_name[CRYPTO_MAX_ALG_NAME];
213 
214 	if (!c->auth_hash_name) {
215 		ubifs_err(c, "authentication hash name needed with authentication");
216 		return -EINVAL;
217 	}
218 
219 	c->auth_hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST,
220 					 c->auth_hash_name);
221 	if ((int)c->auth_hash_algo < 0) {
222 		ubifs_err(c, "Unknown hash algo %s specified",
223 			  c->auth_hash_name);
224 		return -EINVAL;
225 	}
226 
227 	snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
228 		 c->auth_hash_name);
229 
230 	keyring_key = request_key(&key_type_logon, c->auth_key_name, NULL);
231 
232 	if (IS_ERR(keyring_key)) {
233 		ubifs_err(c, "Failed to request key: %ld",
234 			  PTR_ERR(keyring_key));
235 		return PTR_ERR(keyring_key);
236 	}
237 
238 	down_read(&keyring_key->sem);
239 
240 	if (keyring_key->type != &key_type_logon) {
241 		ubifs_err(c, "key type must be logon");
242 		err = -ENOKEY;
243 		goto out;
244 	}
245 
246 	ukp = user_key_payload_locked(keyring_key);
247 	if (!ukp) {
248 		/* key was revoked before we acquired its semaphore */
249 		err = -EKEYREVOKED;
250 		goto out;
251 	}
252 
253 	c->hash_tfm = crypto_alloc_shash(c->auth_hash_name, 0, 0);
254 	if (IS_ERR(c->hash_tfm)) {
255 		err = PTR_ERR(c->hash_tfm);
256 		ubifs_err(c, "Can not allocate %s: %d",
257 			  c->auth_hash_name, err);
258 		goto out;
259 	}
260 
261 	c->hash_len = crypto_shash_digestsize(c->hash_tfm);
262 	if (c->hash_len > UBIFS_HASH_ARR_SZ) {
263 		ubifs_err(c, "hash %s is bigger than maximum allowed hash size (%d > %d)",
264 			  c->auth_hash_name, c->hash_len, UBIFS_HASH_ARR_SZ);
265 		err = -EINVAL;
266 		goto out_free_hash;
267 	}
268 
269 	c->hmac_tfm = crypto_alloc_shash(hmac_name, 0, 0);
270 	if (IS_ERR(c->hmac_tfm)) {
271 		err = PTR_ERR(c->hmac_tfm);
272 		ubifs_err(c, "Can not allocate %s: %d", hmac_name, err);
273 		goto out_free_hash;
274 	}
275 
276 	c->hmac_desc_len = crypto_shash_digestsize(c->hmac_tfm);
277 	if (c->hmac_desc_len > UBIFS_HMAC_ARR_SZ) {
278 		ubifs_err(c, "hmac %s is bigger than maximum allowed hmac size (%d > %d)",
279 			  hmac_name, c->hmac_desc_len, UBIFS_HMAC_ARR_SZ);
280 		err = -EINVAL;
281 		goto out_free_hash;
282 	}
283 
284 	err = crypto_shash_setkey(c->hmac_tfm, ukp->data, ukp->datalen);
285 	if (err)
286 		goto out_free_hmac;
287 
288 	c->authenticated = true;
289 
290 	c->log_hash = ubifs_hash_get_desc(c);
291 	if (IS_ERR(c->log_hash))
292 		goto out_free_hmac;
293 
294 	err = 0;
295 
296 out_free_hmac:
297 	if (err)
298 		crypto_free_shash(c->hmac_tfm);
299 out_free_hash:
300 	if (err)
301 		crypto_free_shash(c->hash_tfm);
302 out:
303 	up_read(&keyring_key->sem);
304 	key_put(keyring_key);
305 
306 	return err;
307 }
308 
309 /**
310  * __ubifs_exit_authentication - release resource
311  * @c: UBIFS file-system description object
312  *
313  * This function releases the authentication related resources.
314  */
315 void __ubifs_exit_authentication(struct ubifs_info *c)
316 {
317 	if (!ubifs_authenticated(c))
318 		return;
319 
320 	crypto_free_shash(c->hmac_tfm);
321 	crypto_free_shash(c->hash_tfm);
322 	kfree(c->log_hash);
323 }
324 
325 /**
326  * ubifs_node_calc_hmac - calculate the HMAC of a UBIFS node
327  * @c: UBIFS file-system description object
328  * @node: the node to insert a HMAC into.
329  * @len: the length of the node
330  * @ofs_hmac: the offset in the node where the HMAC is inserted
331  * @hmac: returned HMAC
332  *
333  * This function calculates a HMAC of a UBIFS node. The HMAC is expected to be
334  * embedded into the node, so this area is not covered by the HMAC. Also not
335  * covered is the UBIFS_NODE_MAGIC and the CRC of the node.
336  */
337 static int ubifs_node_calc_hmac(const struct ubifs_info *c, const void *node,
338 				int len, int ofs_hmac, void *hmac)
339 {
340 	SHASH_DESC_ON_STACK(shash, c->hmac_tfm);
341 	int hmac_len = c->hmac_desc_len;
342 	int err;
343 
344 	ubifs_assert(c, ofs_hmac > 8);
345 	ubifs_assert(c, ofs_hmac + hmac_len < len);
346 
347 	shash->tfm = c->hmac_tfm;
348 
349 	err = crypto_shash_init(shash);
350 	if (err)
351 		return err;
352 
353 	/* behind common node header CRC up to HMAC begin */
354 	err = crypto_shash_update(shash, node + 8, ofs_hmac - 8);
355 	if (err < 0)
356 		return err;
357 
358 	/* behind HMAC, if any */
359 	if (len - ofs_hmac - hmac_len > 0) {
360 		err = crypto_shash_update(shash, node + ofs_hmac + hmac_len,
361 			    len - ofs_hmac - hmac_len);
362 		if (err < 0)
363 			return err;
364 	}
365 
366 	return crypto_shash_final(shash, hmac);
367 }
368 
369 /**
370  * __ubifs_node_insert_hmac - insert a HMAC into a UBIFS node
371  * @c: UBIFS file-system description object
372  * @node: the node to insert a HMAC into.
373  * @len: the length of the node
374  * @ofs_hmac: the offset in the node where the HMAC is inserted
375  *
376  * This function inserts a HMAC at offset @ofs_hmac into the node given in
377  * @node.
378  *
379  * This function returns 0 for success or a negative error code otherwise.
380  */
381 int __ubifs_node_insert_hmac(const struct ubifs_info *c, void *node, int len,
382 			    int ofs_hmac)
383 {
384 	return ubifs_node_calc_hmac(c, node, len, ofs_hmac, node + ofs_hmac);
385 }
386 
387 /**
388  * __ubifs_node_verify_hmac - verify the HMAC of UBIFS node
389  * @c: UBIFS file-system description object
390  * @node: the node to insert a HMAC into.
391  * @len: the length of the node
392  * @ofs_hmac: the offset in the node where the HMAC is inserted
393  *
394  * This function verifies the HMAC at offset @ofs_hmac of the node given in
395  * @node. Returns 0 if successful or a negative error code otherwise.
396  */
397 int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *node,
398 			     int len, int ofs_hmac)
399 {
400 	int hmac_len = c->hmac_desc_len;
401 	u8 *hmac;
402 	int err;
403 
404 	hmac = kmalloc(hmac_len, GFP_NOFS);
405 	if (!hmac)
406 		return -ENOMEM;
407 
408 	err = ubifs_node_calc_hmac(c, node, len, ofs_hmac, hmac);
409 	if (err)
410 		return err;
411 
412 	err = crypto_memneq(hmac, node + ofs_hmac, hmac_len);
413 
414 	kfree(hmac);
415 
416 	if (!err)
417 		return 0;
418 
419 	return -EPERM;
420 }
421 
422 int __ubifs_shash_copy_state(const struct ubifs_info *c, struct shash_desc *src,
423 			     struct shash_desc *target)
424 {
425 	u8 *state;
426 	int err;
427 
428 	state = kmalloc(crypto_shash_descsize(src->tfm), GFP_NOFS);
429 	if (!state)
430 		return -ENOMEM;
431 
432 	err = crypto_shash_export(src, state);
433 	if (err)
434 		goto out;
435 
436 	err = crypto_shash_import(target, state);
437 
438 out:
439 	kfree(state);
440 
441 	return err;
442 }
443 
444 /**
445  * ubifs_hmac_wkm - Create a HMAC of the well known message
446  * @c: UBIFS file-system description object
447  * @hmac: The HMAC of the well known message
448  *
449  * This function creates a HMAC of a well known message. This is used
450  * to check if the provided key is suitable to authenticate a UBIFS
451  * image. This is only a convenience to the user to provide a better
452  * error message when the wrong key is provided.
453  *
454  * This function returns 0 for success or a negative error code otherwise.
455  */
456 int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac)
457 {
458 	SHASH_DESC_ON_STACK(shash, c->hmac_tfm);
459 	int err;
460 	const char well_known_message[] = "UBIFS";
461 
462 	if (!ubifs_authenticated(c))
463 		return 0;
464 
465 	shash->tfm = c->hmac_tfm;
466 
467 	err = crypto_shash_init(shash);
468 	if (err)
469 		return err;
470 
471 	err = crypto_shash_update(shash, well_known_message,
472 				  sizeof(well_known_message) - 1);
473 	if (err < 0)
474 		return err;
475 
476 	err = crypto_shash_final(shash, hmac);
477 	if (err)
478 		return err;
479 	return 0;
480 }
481