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