2019-06-01 11:08:42 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2015-12-04 00:01:51 +03:00
/*
* Copyright ( C ) 2012 Red Hat , Inc .
* Copyright ( C ) 2015 Google , Inc .
*
* Author : Mikulas Patocka < mpatocka @ redhat . com >
*
* Based on Chromium dm - verity driver ( C ) 2011 The Chromium OS Authors
*/
# ifndef DM_VERITY_H
# define DM_VERITY_H
2018-03-15 23:02:31 +03:00
# include <linux/dm-bufio.h>
2015-12-04 00:01:51 +03:00
# include <linux/device-mapper.h>
# include <crypto/hash.h>
# define DM_VERITY_MAX_LEVELS 63
enum verity_mode {
DM_VERITY_MODE_EIO ,
DM_VERITY_MODE_LOGGING ,
2020-06-18 09:56:50 +03:00
DM_VERITY_MODE_RESTART ,
DM_VERITY_MODE_PANIC
2015-12-04 00:01:51 +03:00
} ;
enum verity_block_type {
DM_VERITY_BLOCK_TYPE_DATA ,
DM_VERITY_BLOCK_TYPE_METADATA
} ;
2015-12-03 17:26:30 +03:00
struct dm_verity_fec ;
2015-12-04 00:01:51 +03:00
struct dm_verity {
struct dm_dev * data_dev ;
struct dm_dev * hash_dev ;
struct dm_target * ti ;
struct dm_bufio_client * bufio ;
char * alg_name ;
2017-02-19 15:46:07 +03:00
struct crypto_ahash * tfm ;
2015-12-04 00:01:51 +03:00
u8 * root_digest ; /* digest of the root block */
u8 * salt ; /* salt: its size is salt_size */
2015-12-03 17:26:31 +03:00
u8 * zero_digest ; /* digest for a zero block */
2015-12-04 00:01:51 +03:00
unsigned salt_size ;
sector_t data_start ; /* data offset in 512-byte sectors */
sector_t hash_start ; /* hash start in blocks */
sector_t data_blocks ; /* the number of data blocks */
sector_t hash_blocks ; /* the number of hash blocks */
unsigned char data_dev_block_bits ; /* log2(data blocksize) */
unsigned char hash_dev_block_bits ; /* log2(hash blocksize) */
unsigned char hash_per_block_bits ; /* log2(hashes in hash block) */
unsigned char levels ; /* the number of tree levels */
unsigned char version ;
unsigned digest_size ; /* digest size for the current hash algorithm */
2017-02-19 15:46:07 +03:00
unsigned int ahash_reqsize ; /* the size of temporary space for crypto */
2015-12-04 00:01:51 +03:00
int hash_failed ; /* set to 1 if hash of any block failed */
enum verity_mode mode ; /* mode for handling verification errors */
unsigned corrupted_errs ; /* Number of errors for corrupted blocks */
struct workqueue_struct * verify_wq ;
/* starting blocks for each tree level. 0 is the lowest level. */
sector_t hash_level_block [ DM_VERITY_MAX_LEVELS ] ;
2015-12-03 17:26:30 +03:00
struct dm_verity_fec * fec ; /* forward error correction */
2018-03-23 04:18:04 +03:00
unsigned long * validated_blocks ; /* bitset blocks validated */
2019-07-18 03:46:15 +03:00
char * signature_key_desc ; /* signature keyring reference */
2015-12-04 00:01:51 +03:00
} ;
struct dm_verity_io {
struct dm_verity * v ;
/* original value of bio->bi_end_io */
bio_end_io_t * orig_bi_end_io ;
sector_t block ;
unsigned n_blocks ;
struct bvec_iter iter ;
struct work_struct work ;
/*
* Three variably - size fields follow this struct :
*
2017-02-19 15:46:07 +03:00
* u8 hash_req [ v - > ahash_reqsize ] ;
2015-12-04 00:01:51 +03:00
* u8 real_digest [ v - > digest_size ] ;
* u8 want_digest [ v - > digest_size ] ;
*
2017-02-19 15:46:07 +03:00
* To access them use : verity_io_hash_req ( ) , verity_io_real_digest ( )
2015-12-04 00:01:51 +03:00
* and verity_io_want_digest ( ) .
*/
} ;
2017-02-19 15:46:07 +03:00
static inline struct ahash_request * verity_io_hash_req ( struct dm_verity * v ,
2015-12-04 00:01:51 +03:00
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( struct ahash_request * ) ( io + 1 ) ;
2015-12-04 00:01:51 +03:00
}
static inline u8 * verity_io_real_digest ( struct dm_verity * v ,
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( u8 * ) ( io + 1 ) + v - > ahash_reqsize ;
2015-12-04 00:01:51 +03:00
}
static inline u8 * verity_io_want_digest ( struct dm_verity * v ,
struct dm_verity_io * io )
{
2017-02-19 15:46:07 +03:00
return ( u8 * ) ( io + 1 ) + v - > ahash_reqsize + v - > digest_size ;
2015-12-04 00:01:51 +03:00
}
2015-12-03 17:26:30 +03:00
static inline u8 * verity_io_digest_end ( struct dm_verity * v ,
struct dm_verity_io * io )
{
return verity_io_want_digest ( v , io ) + v - > digest_size ;
}
2015-12-04 00:30:36 +03:00
extern int verity_for_bv_block ( struct dm_verity * v , struct dm_verity_io * io ,
struct bvec_iter * iter ,
int ( * process ) ( struct dm_verity * v ,
struct dm_verity_io * io ,
u8 * data , size_t len ) ) ;
2017-02-19 15:46:07 +03:00
extern int verity_hash ( struct dm_verity * v , struct ahash_request * req ,
2015-12-04 00:01:51 +03:00
const u8 * data , size_t len , u8 * digest ) ;
extern int verity_hash_for_block ( struct dm_verity * v , struct dm_verity_io * io ,
2015-12-03 17:26:31 +03:00
sector_t block , u8 * digest , bool * is_zero ) ;
2015-12-04 00:01:51 +03:00
# endif /* DM_VERITY_H */