mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
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:
parent
cded278212
commit
76905cc1d7
@ -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:
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user