xref: /openbmc/linux/drivers/md/dm-verity-loadpin.c (revision 27603a606fda0806d7c08914bc976931aa42020e)
1b6c1c574SMatthias Kaehlcke // SPDX-License-Identifier: GPL-2.0-only
2b6c1c574SMatthias Kaehlcke 
3b6c1c574SMatthias Kaehlcke #include <linux/list.h>
4b6c1c574SMatthias Kaehlcke #include <linux/kernel.h>
5b6c1c574SMatthias Kaehlcke #include <linux/dm-verity-loadpin.h>
6b6c1c574SMatthias Kaehlcke 
7b6c1c574SMatthias Kaehlcke #include "dm.h"
8*27603a60SMatthias Kaehlcke #include "dm-core.h"
9b6c1c574SMatthias Kaehlcke #include "dm-verity.h"
10b6c1c574SMatthias Kaehlcke 
11b6c1c574SMatthias Kaehlcke #define DM_MSG_PREFIX	"verity-loadpin"
12b6c1c574SMatthias Kaehlcke 
13b6c1c574SMatthias Kaehlcke LIST_HEAD(dm_verity_loadpin_trusted_root_digests);
14b6c1c574SMatthias Kaehlcke 
15b6c1c574SMatthias Kaehlcke static bool is_trusted_verity_target(struct dm_target *ti)
16b6c1c574SMatthias Kaehlcke {
17b6c1c574SMatthias Kaehlcke 	u8 *root_digest;
18b6c1c574SMatthias Kaehlcke 	unsigned int digest_size;
19b6c1c574SMatthias Kaehlcke 	struct dm_verity_loadpin_trusted_root_digest *trd;
20b6c1c574SMatthias Kaehlcke 	bool trusted = false;
21b6c1c574SMatthias Kaehlcke 
22b6c1c574SMatthias Kaehlcke 	if (!dm_is_verity_target(ti))
23b6c1c574SMatthias Kaehlcke 		return false;
24b6c1c574SMatthias Kaehlcke 
25b6c1c574SMatthias Kaehlcke 	if (dm_verity_get_root_digest(ti, &root_digest, &digest_size))
26b6c1c574SMatthias Kaehlcke 		return false;
27b6c1c574SMatthias Kaehlcke 
28b6c1c574SMatthias Kaehlcke 	list_for_each_entry(trd, &dm_verity_loadpin_trusted_root_digests, node) {
29b6c1c574SMatthias Kaehlcke 		if ((trd->len == digest_size) &&
30b6c1c574SMatthias Kaehlcke 		    !memcmp(trd->data, root_digest, digest_size)) {
31b6c1c574SMatthias Kaehlcke 			trusted = true;
32b6c1c574SMatthias Kaehlcke 			break;
33b6c1c574SMatthias Kaehlcke 		}
34b6c1c574SMatthias Kaehlcke 	}
35b6c1c574SMatthias Kaehlcke 
36b6c1c574SMatthias Kaehlcke 	kfree(root_digest);
37b6c1c574SMatthias Kaehlcke 
38b6c1c574SMatthias Kaehlcke 	return trusted;
39b6c1c574SMatthias Kaehlcke }
40b6c1c574SMatthias Kaehlcke 
41b6c1c574SMatthias Kaehlcke /*
42b6c1c574SMatthias Kaehlcke  * Determines whether the file system of a superblock is located on
43b6c1c574SMatthias Kaehlcke  * a verity device that is trusted by LoadPin.
44b6c1c574SMatthias Kaehlcke  */
45b6c1c574SMatthias Kaehlcke bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev)
46b6c1c574SMatthias Kaehlcke {
47b6c1c574SMatthias Kaehlcke 	struct mapped_device *md;
48b6c1c574SMatthias Kaehlcke 	struct dm_table *table;
49b6c1c574SMatthias Kaehlcke 	struct dm_target *ti;
50b6c1c574SMatthias Kaehlcke 	int srcu_idx;
51b6c1c574SMatthias Kaehlcke 	bool trusted = false;
52b6c1c574SMatthias Kaehlcke 
53b6c1c574SMatthias Kaehlcke 	if (list_empty(&dm_verity_loadpin_trusted_root_digests))
54b6c1c574SMatthias Kaehlcke 		return false;
55b6c1c574SMatthias Kaehlcke 
56b6c1c574SMatthias Kaehlcke 	md = dm_get_md(bdev->bd_dev);
57b6c1c574SMatthias Kaehlcke 	if (!md)
58b6c1c574SMatthias Kaehlcke 		return false;
59b6c1c574SMatthias Kaehlcke 
60b6c1c574SMatthias Kaehlcke 	table = dm_get_live_table(md, &srcu_idx);
61b6c1c574SMatthias Kaehlcke 
62*27603a60SMatthias Kaehlcke 	if (table->num_targets != 1)
63b6c1c574SMatthias Kaehlcke 		goto out;
64b6c1c574SMatthias Kaehlcke 
65b6c1c574SMatthias Kaehlcke 	ti = dm_table_get_target(table, 0);
66b6c1c574SMatthias Kaehlcke 
67b6c1c574SMatthias Kaehlcke 	if (is_trusted_verity_target(ti))
68b6c1c574SMatthias Kaehlcke 		trusted = true;
69b6c1c574SMatthias Kaehlcke 
70b6c1c574SMatthias Kaehlcke out:
71b6c1c574SMatthias Kaehlcke 	dm_put_live_table(md, srcu_idx);
72b6c1c574SMatthias Kaehlcke 	dm_put(md);
73b6c1c574SMatthias Kaehlcke 
74b6c1c574SMatthias Kaehlcke 	return trusted;
75b6c1c574SMatthias Kaehlcke }
76