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