xref: /linux/drivers/md/dm-verity.h (revision 9e23acf024895a50306508880a075efa18656322)
155716d26SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2ffa39380SSami Tolvanen /*
3ffa39380SSami Tolvanen  * Copyright (C) 2012 Red Hat, Inc.
4ffa39380SSami Tolvanen  * Copyright (C) 2015 Google, Inc.
5ffa39380SSami Tolvanen  *
6ffa39380SSami Tolvanen  * Author: Mikulas Patocka <mpatocka@redhat.com>
7ffa39380SSami Tolvanen  *
8ffa39380SSami Tolvanen  * Based on Chromium dm-verity driver (C) 2011 The Chromium OS Authors
9ffa39380SSami Tolvanen  */
10ffa39380SSami Tolvanen 
11ffa39380SSami Tolvanen #ifndef DM_VERITY_H
12ffa39380SSami Tolvanen #define DM_VERITY_H
13ffa39380SSami Tolvanen 
149177f3c0SMikulas Patocka #include <linux/dm-io.h>
15afa53df8SMikulas Patocka #include <linux/dm-bufio.h>
16ffa39380SSami Tolvanen #include <linux/device-mapper.h>
175721d4e5SNathan Huckleberry #include <linux/interrupt.h>
18ffa39380SSami Tolvanen #include <crypto/hash.h>
19ffa39380SSami Tolvanen 
20ffa39380SSami Tolvanen #define DM_VERITY_MAX_LEVELS		63
21ffa39380SSami Tolvanen 
22ffa39380SSami Tolvanen enum verity_mode {
23ffa39380SSami Tolvanen 	DM_VERITY_MODE_EIO,
24ffa39380SSami Tolvanen 	DM_VERITY_MODE_LOGGING,
25e1fef0b0SJeongHyeon Lee 	DM_VERITY_MODE_RESTART,
26e1fef0b0SJeongHyeon Lee 	DM_VERITY_MODE_PANIC
27ffa39380SSami Tolvanen };
28ffa39380SSami Tolvanen 
29ffa39380SSami Tolvanen enum verity_block_type {
30ffa39380SSami Tolvanen 	DM_VERITY_BLOCK_TYPE_DATA,
31ffa39380SSami Tolvanen 	DM_VERITY_BLOCK_TYPE_METADATA
32ffa39380SSami Tolvanen };
33ffa39380SSami Tolvanen 
34a739ff3fSSami Tolvanen struct dm_verity_fec;
35a739ff3fSSami Tolvanen 
36ffa39380SSami Tolvanen struct dm_verity {
37ffa39380SSami Tolvanen 	struct dm_dev *data_dev;
38ffa39380SSami Tolvanen 	struct dm_dev *hash_dev;
39ffa39380SSami Tolvanen 	struct dm_target *ti;
40ffa39380SSami Tolvanen 	struct dm_bufio_client *bufio;
41ffa39380SSami Tolvanen 	char *alg_name;
42b76ad884SEric Biggers 	struct crypto_ahash *ahash_tfm; /* either this or shash_tfm is set */
43b76ad884SEric Biggers 	struct crypto_shash *shash_tfm; /* either this or ahash_tfm is set */
44ffa39380SSami Tolvanen 	u8 *root_digest;	/* digest of the root block */
45ffa39380SSami Tolvanen 	u8 *salt;		/* salt: its size is salt_size */
46b76ad884SEric Biggers 	u8 *initial_hashstate;	/* salted initial state, if shash_tfm is set */
470cc37c2dSSami Tolvanen 	u8 *zero_digest;	/* digest for a zero block */
48a6af7bc3SDeven Bowers #ifdef CONFIG_SECURITY
49a6af7bc3SDeven Bowers 	u8 *root_digest_sig;	/* signature of the root digest */
50a6af7bc3SDeven Bowers 	unsigned int sig_size;	/* root digest signature size */
51a6af7bc3SDeven Bowers #endif /* CONFIG_SECURITY */
5286a3238cSHeinz Mauelshagen 	unsigned int salt_size;
53ffa39380SSami Tolvanen 	sector_t data_start;	/* data offset in 512-byte sectors */
54ffa39380SSami Tolvanen 	sector_t hash_start;	/* hash start in blocks */
55ffa39380SSami Tolvanen 	sector_t data_blocks;	/* the number of data blocks */
56ffa39380SSami Tolvanen 	sector_t hash_blocks;	/* the number of hash blocks */
57ffa39380SSami Tolvanen 	unsigned char data_dev_block_bits;	/* log2(data blocksize) */
58ffa39380SSami Tolvanen 	unsigned char hash_dev_block_bits;	/* log2(hash blocksize) */
59ffa39380SSami Tolvanen 	unsigned char hash_per_block_bits;	/* log2(hashes in hash block) */
60ffa39380SSami Tolvanen 	unsigned char levels;	/* the number of tree levels */
61ffa39380SSami Tolvanen 	unsigned char version;
625721d4e5SNathan Huckleberry 	bool hash_failed:1;	/* set if hash of any block failed */
63c375b223STejun Heo 	bool use_bh_wq:1;	/* try to verify in BH wq before normal work-queue */
6486a3238cSHeinz Mauelshagen 	unsigned int digest_size;	/* digest size for the current hash algorithm */
65b76ad884SEric Biggers 	unsigned int hash_reqsize; /* the size of temporary space for crypto */
66ffa39380SSami Tolvanen 	enum verity_mode mode;	/* mode for handling verification errors */
67f811b838SMikulas Patocka 	enum verity_mode error_mode;/* mode for handling I/O errors */
6886a3238cSHeinz Mauelshagen 	unsigned int corrupted_errs;/* Number of errors for corrupted blocks */
69ffa39380SSami Tolvanen 
70ffa39380SSami Tolvanen 	struct workqueue_struct *verify_wq;
71ffa39380SSami Tolvanen 
72ffa39380SSami Tolvanen 	/* starting blocks for each tree level. 0 is the lowest level. */
73ffa39380SSami Tolvanen 	sector_t hash_level_block[DM_VERITY_MAX_LEVELS];
74a739ff3fSSami Tolvanen 
75a739ff3fSSami Tolvanen 	struct dm_verity_fec *fec;	/* forward error correction */
76843f38d3SPatrik Torstensson 	unsigned long *validated_blocks; /* bitset blocks validated */
7788cd3e6cSJaskaran Khurana 
7888cd3e6cSJaskaran Khurana 	char *signature_key_desc; /* signature keyring reference */
799177f3c0SMikulas Patocka 
809177f3c0SMikulas Patocka 	struct dm_io_client *io;
819177f3c0SMikulas Patocka 	mempool_t recheck_pool;
82ffa39380SSami Tolvanen };
83ffa39380SSami Tolvanen 
84ffa39380SSami Tolvanen struct dm_verity_io {
85ffa39380SSami Tolvanen 	struct dm_verity *v;
86ffa39380SSami Tolvanen 
87ffa39380SSami Tolvanen 	/* original value of bio->bi_end_io */
88ffa39380SSami Tolvanen 	bio_end_io_t *orig_bi_end_io;
89ffa39380SSami Tolvanen 
90787f1b28SMikulas Patocka 	struct bvec_iter iter;
91787f1b28SMikulas Patocka 
92ffa39380SSami Tolvanen 	sector_t block;
9386a3238cSHeinz Mauelshagen 	unsigned int n_blocks;
94c375b223STejun Heo 	bool in_bh;
95*a674d0cdSMikulas Patocka 	bool had_mismatch;
96ffa39380SSami Tolvanen 
97ffa39380SSami Tolvanen 	struct work_struct work;
98c375b223STejun Heo 	struct work_struct bh_work;
99ffa39380SSami Tolvanen 
100a7ddb3d4SEric Biggers 	u8 real_digest[HASH_MAX_DIGESTSIZE];
101a7ddb3d4SEric Biggers 	u8 want_digest[HASH_MAX_DIGESTSIZE];
102a7ddb3d4SEric Biggers 
103ffa39380SSami Tolvanen 	/*
104b76ad884SEric Biggers 	 * This struct is followed by a variable-sized hash request of size
105b76ad884SEric Biggers 	 * v->hash_reqsize, either a struct ahash_request or a struct shash_desc
106b76ad884SEric Biggers 	 * (depending on whether ahash_tfm or shash_tfm is being used).  To
107b76ad884SEric Biggers 	 * access it, use verity_io_hash_req().
108ffa39380SSami Tolvanen 	 */
109ffa39380SSami Tolvanen };
110ffa39380SSami Tolvanen 
verity_io_hash_req(struct dm_verity * v,struct dm_verity_io * io)111b76ad884SEric Biggers static inline void *verity_io_hash_req(struct dm_verity *v,
112ffa39380SSami Tolvanen 				       struct dm_verity_io *io)
113ffa39380SSami Tolvanen {
114b76ad884SEric Biggers 	return io + 1;
115ffa39380SSami Tolvanen }
116ffa39380SSami Tolvanen 
verity_io_real_digest(struct dm_verity * v,struct dm_verity_io * io)117ffa39380SSami Tolvanen static inline u8 *verity_io_real_digest(struct dm_verity *v,
118ffa39380SSami Tolvanen 					struct dm_verity_io *io)
119ffa39380SSami Tolvanen {
120a7ddb3d4SEric Biggers 	return io->real_digest;
121ffa39380SSami Tolvanen }
122ffa39380SSami Tolvanen 
verity_io_want_digest(struct dm_verity * v,struct dm_verity_io * io)123ffa39380SSami Tolvanen static inline u8 *verity_io_want_digest(struct dm_verity *v,
124ffa39380SSami Tolvanen 					struct dm_verity_io *io)
125ffa39380SSami Tolvanen {
126a7ddb3d4SEric Biggers 	return io->want_digest;
127ffa39380SSami Tolvanen }
128ffa39380SSami Tolvanen 
129e8f5e933SEric Biggers extern int verity_hash(struct dm_verity *v, struct dm_verity_io *io,
13028f07f2aSMikulas Patocka 		       const u8 *data, size_t len, u8 *digest, bool may_sleep);
131ffa39380SSami Tolvanen 
132ffa39380SSami Tolvanen extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
1330cc37c2dSSami Tolvanen 				 sector_t block, u8 *digest, bool *is_zero);
134ffa39380SSami Tolvanen 
135b6c1c574SMatthias Kaehlcke extern bool dm_is_verity_target(struct dm_target *ti);
136916ef623SMatthias Kaehlcke extern int dm_verity_get_mode(struct dm_target *ti);
137b6c1c574SMatthias Kaehlcke extern int dm_verity_get_root_digest(struct dm_target *ti, u8 **root_digest,
138b6c1c574SMatthias Kaehlcke 				     unsigned int *digest_size);
139b6c1c574SMatthias Kaehlcke 
140ffa39380SSami Tolvanen #endif /* DM_VERITY_H */
141