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 <sspatil@google.com>

Change-Id: I1e29111d57b62f0451404c08d49145039dd00737
This commit is contained in:
Sandeep Patil 2018-07-23 16:31:32 -07:00 committed by Alistair Strachan
parent cded278212
commit 76905cc1d7
2 changed files with 102 additions and 125 deletions

View File

@ -33,6 +33,7 @@
#include <asm/setup.h>
#include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/public_key.h>
#include <crypto/sha.h>
#include <keys/asymmetric-type.h>
@ -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:

View File

@ -120,8 +120,9 @@ extern int dm_linear_prepare_ioctl(struct dm_target *ti,
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);
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);
#endif /* DM_ANDROID_VERITY_H */