From 1a8ef4e83669ebccb9090e0a90bc23a2a55241ec Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Mon, 23 Jul 2018 16:31:32 -0700 Subject: [PATCH] ANDROID: android-verity: Make it work with newer kernels Fixed bio API calls as they changed from 4.4 to 4.9. Fixed the driver to use the new verify_signature_one() API. Remove the dead code resulted from the rebase. Bug: 72722987 Test: Build and boot hikey with system partition mounted as root using android-verity Signed-off-by: Sandeep Patil Change-Id: I1e29111d57b62f0451404c08d49145039dd00737 --- drivers/md/dm-android-verity.c | 222 +++++++++++++++------------------ drivers/md/dm-android-verity.h | 5 +- 2 files changed, 102 insertions(+), 125 deletions(-) diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c index 0dd69244f77c..ce8dcfdee264 100644 --- a/drivers/md/dm-android-verity.c +++ b/drivers/md/dm-android-verity.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -122,75 +123,6 @@ static inline bool is_unlocked(void) return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked)); } -static int table_extract_mpi_array(struct public_key_signature *pks, - const void *data, size_t len) -{ - MPI mpi = mpi_read_raw_data(data, len); - - if (!mpi) { - DMERR("Error while allocating mpi array"); - return -ENOMEM; - } - - pks->mpi[0] = mpi; - pks->nr_mpi = 1; - return 0; -} - -static struct public_key_signature *table_make_digest( - enum hash_algo hash, - const void *table, - unsigned long table_len) -{ - struct public_key_signature *pks = NULL; - struct crypto_shash *tfm; - struct shash_desc *desc; - size_t digest_size, desc_size; - int ret; - - /* Allocate the hashing algorithm we're going to need and find out how - * big the hash operational data will be. - */ - tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0); - if (IS_ERR(tfm)) - return ERR_CAST(tfm); - - desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - digest_size = crypto_shash_digestsize(tfm); - - /* We allocate the hash operational data storage on the end of out - * context data and the digest output buffer on the end of that. - */ - ret = -ENOMEM; - pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); - if (!pks) - goto error; - - pks->pkey_hash_algo = hash; - pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; - pks->digest_size = digest_size; - - desc = (struct shash_desc *)(pks + 1); - desc->tfm = tfm; - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - - ret = crypto_shash_init(desc); - if (ret < 0) - goto error; - - ret = crypto_shash_finup(desc, table, table_len, pks->digest); - if (ret < 0) - goto error; - - crypto_free_shash(tfm); - return pks; - -error: - kfree(pks); - crypto_free_shash(tfm); - return ERR_PTR(ret); -} - static int read_block_dev(struct bio_read *payload, struct block_device *bdev, sector_t offset, int length) { @@ -205,8 +137,9 @@ static int read_block_dev(struct bio_read *payload, struct block_device *bdev, return -ENOMEM; } - bio->bi_bdev = bdev; + bio_set_dev(bio, bdev); bio->bi_iter.bi_sector = offset; + bio_set_op_attrs(bio, REQ_OP_READ, 0); payload->page_io = kzalloc(sizeof(struct page *) * payload->number_of_pages, GFP_KERNEL); @@ -230,7 +163,7 @@ static int read_block_dev(struct bio_read *payload, struct block_device *bdev, } } - if (!submit_bio_wait(READ, bio)) + if (!submit_bio_wait(bio)) /* success */ goto free_bio; DMERR("bio read failed"); @@ -567,51 +500,6 @@ static int verity_mode(void) return DM_VERITY_MODE_EIO; } -static int verify_verity_signature(char *key_id, - struct android_metadata *metadata) -{ - key_ref_t key_ref; - struct key *key; - struct public_key_signature *pks = NULL; - int retval = -EINVAL; - - key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1), - &key_type_asymmetric, key_id); - - if (IS_ERR(key_ref)) { - DMERR("keyring: key not found"); - return -ENOKEY; - } - - key = key_ref_to_ptr(key_ref); - - pks = table_make_digest(HASH_ALGO_SHA256, - (const void *)metadata->verity_table, - le32_to_cpu(metadata->header->table_length)); - - if (IS_ERR(pks)) { - DMERR("hashing failed"); - retval = PTR_ERR(pks); - pks = NULL; - goto error; - } - - retval = table_extract_mpi_array(pks, &metadata->header->signature[0], - RSANUMBYTES); - if (retval < 0) { - DMERR("Error extracting mpi %d", retval); - goto error; - } - - retval = verify_signature(key, pks); - mpi_free(pks->rsa.s); -error: - kfree(pks); - key_put(key); - - return retval; -} - static void handle_error(void) { int mode = verity_mode(); @@ -623,6 +511,95 @@ static void handle_error(void) } } +static struct public_key_signature *table_make_digest( + enum hash_algo hash, + const void *table, + unsigned long table_len) +{ + struct public_key_signature *pks = NULL; + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t digest_size, desc_size; + int ret; + + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ + tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0); + if (IS_ERR(tfm)) + return ERR_CAST(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + digest_size = crypto_shash_digestsize(tfm); + + /* We allocate the hash operational data storage on the end of out + * context data and the digest output buffer on the end of that. + */ + ret = -ENOMEM; + pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); + if (!pks) + goto error; + + pks->pkey_algo = "rsa"; + pks->hash_algo = hash_algo_name[hash]; + pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; + pks->digest_size = digest_size; + + desc = (struct shash_desc *)(pks + 1); + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error; + + ret = crypto_shash_finup(desc, table, table_len, pks->digest); + if (ret < 0) + goto error; + + crypto_free_shash(tfm); + return pks; + +error: + kfree(pks); + crypto_free_shash(tfm); + return ERR_PTR(ret); +} + + +static int verify_verity_signature(char *key_id, + struct android_metadata *metadata) +{ + struct public_key_signature *pks = NULL; + int retval = -EINVAL; + + if (!key_id) + goto error; + + pks = table_make_digest(HASH_ALGO_SHA256, + (const void *)metadata->verity_table, + le32_to_cpu(metadata->header->table_length)); + if (IS_ERR(pks)) { + DMERR("hashing failed"); + retval = PTR_ERR(pks); + pks = NULL; + goto error; + } + + pks->s = kmemdup(&metadata->header->signature[0], RSANUMBYTES, GFP_KERNEL); + if (!pks->s) { + DMERR("Error allocating memory for signature"); + goto error; + } + pks->s_size = RSANUMBYTES; + + retval = verify_signature_one(pks, NULL, key_id); + kfree(pks->s); +error: + kfree(pks); + return retval; +} + static inline bool test_mult_overflow(sector_t a, u32 b) { sector_t r = (sector_t)~0ULL; @@ -696,8 +673,8 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv) dev_t uninitialized_var(dev); struct android_metadata *metadata = NULL; int err = 0, i, mode; - char *key_id, *table_ptr, dummy, *target_device, - *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS]; + char *key_id = NULL, *table_ptr, dummy, *target_device; + char *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS]; /* One for specifying number of opt args and one for mode */ sector_t data_sectors; u32 data_block_size; @@ -879,12 +856,11 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } err = verity_ctr(ti, no_of_args, verity_table_args); - - if (err) - DMERR("android-verity failed to mount as verity target"); - else { + if (err) { + DMERR("android-verity failed to create a verity target"); + } else { target_added = true; - DMINFO("android-verity mounted as verity target"); + DMINFO("android-verity created as verity target"); } free_metadata: diff --git a/drivers/md/dm-android-verity.h b/drivers/md/dm-android-verity.h index a637accefb5b..8f6f5e777187 100644 --- a/drivers/md/dm-android-verity.h +++ b/drivers/md/dm-android-verity.h @@ -120,8 +120,9 @@ extern int dm_linear_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data); extern int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv); #if IS_ENABLED(CONFIG_DAX_DRIVER) -extern long dm_linear_dax_direct_access(struct dm_target *ti, sector_t sector, - void **kaddr, pfn_t *pfn, long size); +extern long dm_linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, + long nr_pages, void **kaddr, + pfn_t *pfn); extern size_t dm_linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i); #else