blob: 999e75bf2ba00fa804219593cdc265861370b0b9 [file] [log] [blame]
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -08001/*
2 * Copyright (C) 2015 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/buffer_head.h>
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -070016#include <linux/debugfs.h>
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -080017#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/device-mapper.h>
20#include <linux/errno.h>
21#include <linux/fs.h>
22#include <linux/fcntl.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/key.h>
26#include <linux/module.h>
27#include <linux/mount.h>
28#include <linux/namei.h>
29#include <linux/of.h>
30#include <linux/reboot.h>
31#include <linux/string.h>
32#include <linux/vmalloc.h>
33
34#include <asm/setup.h>
35#include <crypto/hash.h>
36#include <crypto/public_key.h>
37#include <crypto/sha.h>
38#include <keys/asymmetric-type.h>
39#include <keys/system_keyring.h>
40
41#include "dm-verity.h"
42#include "dm-android-verity.h"
43
44static char verifiedbootstate[VERITY_COMMANDLINE_PARAM_LENGTH];
45static char veritymode[VERITY_COMMANDLINE_PARAM_LENGTH];
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -070046static char veritykeyid[VERITY_DEFAULT_KEY_ID_LENGTH];
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -070047static char buildvariant[BUILD_VARIANT];
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -080048
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -070049static bool target_added;
50static bool verity_enabled = true;
51struct dentry *debug_dir;
52static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv);
53
54static struct target_type android_verity_target = {
55 .name = "android-verity",
56 .version = {1, 0, 0},
57 .module = THIS_MODULE,
58 .ctr = android_verity_ctr,
59 .dtr = verity_dtr,
60 .map = verity_map,
61 .status = verity_status,
62 .ioctl = verity_ioctl,
63 .merge = verity_merge,
64 .iterate_devices = verity_iterate_devices,
65 .io_hints = verity_io_hints,
66};
67
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -080068static int __init verified_boot_state_param(char *line)
69{
70 strlcpy(verifiedbootstate, line, sizeof(verifiedbootstate));
71 return 1;
72}
73
74__setup("androidboot.verifiedbootstate=", verified_boot_state_param);
75
76static int __init verity_mode_param(char *line)
77{
78 strlcpy(veritymode, line, sizeof(veritymode));
79 return 1;
80}
81
82__setup("androidboot.veritymode=", verity_mode_param);
83
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -070084static int __init verity_keyid_param(char *line)
85{
86 strlcpy(veritykeyid, line, sizeof(veritykeyid));
87 return 1;
88}
89
90__setup("veritykeyid=", verity_keyid_param);
91
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -070092static int __init verity_buildvariant(char *line)
93{
94 strlcpy(buildvariant, line, sizeof(buildvariant));
95 return 1;
96}
97
98__setup("buildvariant=", verity_buildvariant);
99
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700100static inline bool default_verity_key_id(void)
101{
102 return veritykeyid[0] != '\0';
103}
104
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700105static inline bool is_eng(void)
106{
107 static const char typeeng[] = "eng";
108
109 return !strncmp(buildvariant, typeeng, sizeof(typeeng));
110}
111
Badhri Jagan Sridharand5943e02016-06-27 16:25:55 -0700112static inline bool is_userdebug(void)
113{
114 static const char typeuserdebug[] = "userdebug";
115
116 return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
117}
118
119
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800120static int table_extract_mpi_array(struct public_key_signature *pks,
121 const void *data, size_t len)
122{
123 MPI mpi = mpi_read_raw_data(data, len);
124
125 if (!mpi) {
126 DMERR("Error while allocating mpi array");
127 return -ENOMEM;
128 }
129
130 pks->mpi[0] = mpi;
131 pks->nr_mpi = 1;
132 return 0;
133}
134
135static struct public_key_signature *table_make_digest(
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800136 enum hash_algo hash,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800137 const void *table,
138 unsigned long table_len)
139{
140 struct public_key_signature *pks = NULL;
141 struct crypto_shash *tfm;
142 struct shash_desc *desc;
143 size_t digest_size, desc_size;
144 int ret;
145
146 /* Allocate the hashing algorithm we're going to need and find out how
147 * big the hash operational data will be.
148 */
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800149 tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800150 if (IS_ERR(tfm))
151 return ERR_CAST(tfm);
152
153 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
154 digest_size = crypto_shash_digestsize(tfm);
155
156 /* We allocate the hash operational data storage on the end of out
157 * context data and the digest output buffer on the end of that.
158 */
159 ret = -ENOMEM;
160 pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
161 if (!pks)
162 goto error;
163
164 pks->pkey_hash_algo = hash;
165 pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
166 pks->digest_size = digest_size;
167
168 desc = (struct shash_desc *)(pks + 1);
169 desc->tfm = tfm;
170 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
171
172 ret = crypto_shash_init(desc);
173 if (ret < 0)
174 goto error;
175
176 ret = crypto_shash_finup(desc, table, table_len, pks->digest);
177 if (ret < 0)
178 goto error;
179
180 crypto_free_shash(tfm);
181 return pks;
182
183error:
184 kfree(pks);
185 crypto_free_shash(tfm);
186 return ERR_PTR(ret);
187}
188
189static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
190 sector_t offset, int length)
191{
192 struct bio *bio;
193 int err = 0, i;
194
195 payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);
196
197 bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
198 if (!bio) {
199 DMERR("Error while allocating bio");
200 return -ENOMEM;
201 }
202
203 bio->bi_bdev = bdev;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800204 bio->bi_iter.bi_sector = offset;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800205
206 payload->page_io = kzalloc(sizeof(struct page *) *
207 payload->number_of_pages, GFP_KERNEL);
208 if (!payload->page_io) {
209 DMERR("page_io array alloc failed");
210 err = -ENOMEM;
211 goto free_bio;
212 }
213
214 for (i = 0; i < payload->number_of_pages; i++) {
215 payload->page_io[i] = alloc_page(GFP_KERNEL);
216 if (!payload->page_io[i]) {
217 DMERR("alloc_page failed");
218 err = -ENOMEM;
219 goto free_pages;
220 }
221 if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
222 DMERR("bio_add_page error");
223 err = -EIO;
224 goto free_pages;
225 }
226 }
227
228 if (!submit_bio_wait(READ, bio))
229 /* success */
230 goto free_bio;
231 DMERR("bio read failed");
232 err = -EIO;
233
234free_pages:
235 for (i = 0; i < payload->number_of_pages; i++)
236 if (payload->page_io[i])
237 __free_page(payload->page_io[i]);
238 kfree(payload->page_io);
239free_bio:
240 bio_put(bio);
241 return err;
242}
243
244static inline u64 fec_div_round_up(u64 x, u64 y)
245{
246 u64 remainder;
247
248 return div64_u64_rem(x, y, &remainder) +
249 (remainder > 0 ? 1 : 0);
250}
251
252static inline void populate_fec_metadata(struct fec_header *header,
253 struct fec_ecc_metadata *ecc)
254{
255 ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
256 FEC_BLOCK_SIZE);
257 ecc->roots = le32_to_cpu(header->roots);
258 ecc->start = le64_to_cpu(header->inp_size);
259}
260
261static inline int validate_fec_header(struct fec_header *header, u64 offset)
262{
263 /* move offset to make the sanity check work for backup header
264 * as well. */
265 offset -= offset % FEC_BLOCK_SIZE;
266 if (le32_to_cpu(header->magic) != FEC_MAGIC ||
267 le32_to_cpu(header->version) != FEC_VERSION ||
268 le32_to_cpu(header->size) != sizeof(struct fec_header) ||
269 le32_to_cpu(header->roots) == 0 ||
270 le32_to_cpu(header->roots) >= FEC_RSM ||
271 offset < le32_to_cpu(header->fec_size) ||
272 offset - le32_to_cpu(header->fec_size) !=
273 le64_to_cpu(header->inp_size))
274 return -EINVAL;
275
276 return 0;
277}
278
279static int extract_fec_header(dev_t dev, struct fec_header *fec,
280 struct fec_ecc_metadata *ecc)
281{
282 u64 device_size;
283 struct bio_read payload;
284 int i, err = 0;
285 struct block_device *bdev;
286
287 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
288
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700289 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800290 DMERR("bdev get error");
291 return PTR_ERR(bdev);
292 }
293
294 device_size = i_size_read(bdev->bd_inode);
295
296 /* fec metadata size is a power of 2 and PAGE_SIZE
297 * is a power of 2 as well.
298 */
299 BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
300 /* 512 byte sector alignment */
301 BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);
302
303 err = read_block_dev(&payload, bdev, (device_size -
304 FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
305 if (err) {
306 DMERR("Error while reading verity metadata");
307 goto error;
308 }
309
310 BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
311 memcpy(fec, page_address(payload.page_io[0]),
312 sizeof(*fec));
313
314 ecc->valid = true;
315 if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
316 /* Try the backup header */
317 memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
318 - sizeof(*fec) ,
319 sizeof(*fec));
320 if (validate_fec_header(fec, device_size -
321 sizeof(struct fec_header)))
322 ecc->valid = false;
323 }
324
325 if (ecc->valid)
326 populate_fec_metadata(fec, ecc);
327
328 for (i = 0; i < payload.number_of_pages; i++)
329 __free_page(payload.page_io[i]);
330 kfree(payload.page_io);
331
332error:
333 blkdev_put(bdev, FMODE_READ);
334 return err;
335}
336static void find_metadata_offset(struct fec_header *fec,
337 struct block_device *bdev, u64 *metadata_offset)
338{
339 u64 device_size;
340
341 device_size = i_size_read(bdev->bd_inode);
342
343 if (le32_to_cpu(fec->magic) == FEC_MAGIC)
344 *metadata_offset = le64_to_cpu(fec->inp_size) -
345 VERITY_METADATA_SIZE;
346 else
347 *metadata_offset = device_size - VERITY_METADATA_SIZE;
348}
349
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700350static int find_size(dev_t dev, u64 *device_size)
351{
352 struct block_device *bdev;
353
354 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
355 if (IS_ERR_OR_NULL(bdev)) {
356 DMERR("blkdev_get_by_dev failed");
357 return PTR_ERR(bdev);
358 }
359
360 *device_size = i_size_read(bdev->bd_inode);
361 *device_size >>= SECTOR_SHIFT;
362
363 DMINFO("blkdev size in sectors: %llu", *device_size);
364 blkdev_put(bdev, FMODE_READ);
365 return 0;
366}
367
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800368static struct android_metadata *extract_metadata(dev_t dev,
369 struct fec_header *fec)
370{
371 struct block_device *bdev;
372 struct android_metadata_header *header;
373 struct android_metadata *uninitialized_var(metadata);
374 int i;
375 u32 table_length, copy_length, offset;
376 u64 metadata_offset;
377 struct bio_read payload;
378 int err = 0;
379
380 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
381
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700382 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800383 DMERR("blkdev_get_by_dev failed");
384 return ERR_CAST(bdev);
385 }
386
387 find_metadata_offset(fec, bdev, &metadata_offset);
388
389 /* Verity metadata size is a power of 2 and PAGE_SIZE
390 * is a power of 2 as well.
391 * PAGE_SIZE is also a multiple of 512 bytes.
392 */
393 if (VERITY_METADATA_SIZE > PAGE_SIZE)
394 BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
395 /* 512 byte sector alignment */
396 BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);
397
398 err = read_block_dev(&payload, bdev, metadata_offset /
399 (1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
400 if (err) {
401 DMERR("Error while reading verity metadata");
402 metadata = ERR_PTR(err);
403 goto blkdev_release;
404 }
405
406 header = kzalloc(sizeof(*header), GFP_KERNEL);
407 if (!header) {
408 DMERR("kzalloc failed for header");
409 err = -ENOMEM;
410 goto free_payload;
411 }
412
413 memcpy(header, page_address(payload.page_io[0]),
414 sizeof(*header));
415
416 DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
417 le32_to_cpu(header->magic_number),
418 le32_to_cpu(header->protocol_version),
419 le32_to_cpu(header->table_length));
420
421 metadata = kzalloc(sizeof(*metadata), GFP_KERNEL);
422 if (!metadata) {
423 DMERR("kzalloc for metadata failed");
424 err = -ENOMEM;
425 goto free_header;
426 }
427
428 metadata->header = header;
429 table_length = le32_to_cpu(header->table_length);
430
431 if (table_length == 0 ||
432 table_length > (VERITY_METADATA_SIZE -
433 sizeof(struct android_metadata_header)))
434 goto free_metadata;
435
436 metadata->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
437
438 if (!metadata->verity_table) {
439 DMERR("kzalloc verity_table failed");
440 err = -ENOMEM;
441 goto free_metadata;
442 }
443
444 if (sizeof(struct android_metadata_header) +
445 table_length <= PAGE_SIZE) {
446 memcpy(metadata->verity_table, page_address(payload.page_io[0])
447 + sizeof(struct android_metadata_header),
448 table_length);
449 } else {
450 copy_length = PAGE_SIZE -
451 sizeof(struct android_metadata_header);
452 memcpy(metadata->verity_table, page_address(payload.page_io[0])
453 + sizeof(struct android_metadata_header),
454 copy_length);
455 table_length -= copy_length;
456 offset = copy_length;
457 i = 1;
458 while (table_length != 0) {
459 if (table_length > PAGE_SIZE) {
460 memcpy(metadata->verity_table + offset,
461 page_address(payload.page_io[i]),
462 PAGE_SIZE);
463 offset += PAGE_SIZE;
464 table_length -= PAGE_SIZE;
465 } else {
466 memcpy(metadata->verity_table + offset,
467 page_address(payload.page_io[i]),
468 table_length);
469 table_length = 0;
470 }
471 i++;
472 }
473 }
474 metadata->verity_table[table_length] = '\0';
475
476 goto free_payload;
477
478free_metadata:
479 kfree(metadata);
480free_header:
481 kfree(header);
482 metadata = ERR_PTR(err);
483free_payload:
484 for (i = 0; i < payload.number_of_pages; i++)
485 if (payload.page_io[i])
486 __free_page(payload.page_io[i]);
487 kfree(payload.page_io);
488
489 DMINFO("verity_table: %s", metadata->verity_table);
490blkdev_release:
491 blkdev_put(bdev, FMODE_READ);
492 return metadata;
493}
494
495/* helper functions to extract properties from dts */
496const char *find_dt_value(const char *name)
497{
498 struct device_node *firmware;
499 const char *value;
500
501 firmware = of_find_node_by_path("/firmware/android");
502 if (!firmware)
503 return NULL;
504 value = of_get_property(firmware, name, NULL);
505 of_node_put(firmware);
506
507 return value;
508}
509
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800510static int verity_mode(void)
511{
512 static const char enforcing[] = "enforcing";
513 static const char verified_mode_prop[] = "veritymode";
514 const char *value;
515
516 value = find_dt_value(verified_mode_prop);
517 if (!value)
518 value = veritymode;
519 if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
520 return DM_VERITY_MODE_RESTART;
521
522 return DM_VERITY_MODE_EIO;
523}
524
525static int verify_header(struct android_metadata_header *header)
526{
527 int retval = -EINVAL;
528
Badhri Jagan Sridharand5943e02016-06-27 16:25:55 -0700529 if (is_userdebug() && le32_to_cpu(header->magic_number) ==
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800530 VERITY_METADATA_MAGIC_DISABLE) {
531 retval = VERITY_STATE_DISABLE;
532 return retval;
533 }
534
535 if (!(le32_to_cpu(header->magic_number) ==
536 VERITY_METADATA_MAGIC_NUMBER) ||
537 (le32_to_cpu(header->magic_number) ==
538 VERITY_METADATA_MAGIC_DISABLE)) {
539 DMERR("Incorrect magic number");
540 return retval;
541 }
542
543 if (le32_to_cpu(header->protocol_version) !=
544 VERITY_METADATA_VERSION) {
545 DMERR("Unsupported version %u",
546 le32_to_cpu(header->protocol_version));
547 return retval;
548 }
549
550 return 0;
551}
552
553static int verify_verity_signature(char *key_id,
554 struct android_metadata *metadata)
555{
556 key_ref_t key_ref;
557 struct key *key;
558 struct public_key_signature *pks = NULL;
559 int retval = -EINVAL;
560
561 key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1),
562 &key_type_asymmetric, key_id);
563
564 if (IS_ERR(key_ref)) {
565 DMERR("keyring: key not found");
566 return -ENOKEY;
567 }
568
569 key = key_ref_to_ptr(key_ref);
570
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800571 pks = table_make_digest(HASH_ALGO_SHA256,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800572 (const void *)metadata->verity_table,
573 le32_to_cpu(metadata->header->table_length));
574
575 if (IS_ERR(pks)) {
576 DMERR("hashing failed");
577 goto error;
578 }
579
580 retval = table_extract_mpi_array(pks, &metadata->header->signature[0],
581 RSANUMBYTES);
582 if (retval < 0) {
583 DMERR("Error extracting mpi %d", retval);
584 goto error;
585 }
586
587 retval = verify_signature(key, pks);
588 mpi_free(pks->rsa.s);
589error:
590 kfree(pks);
591 key_put(key);
592
593 return retval;
594}
595
596static void handle_error(void)
597{
598 int mode = verity_mode();
599 if (mode == DM_VERITY_MODE_RESTART) {
600 DMERR("triggering restart");
601 kernel_restart("dm-verity device corrupted");
602 } else {
603 DMERR("Mounting verity root failed");
604 }
605}
606
607static inline bool test_mult_overflow(sector_t a, u32 b)
608{
609 sector_t r = (sector_t)~0ULL;
610
611 sector_div(r, b);
612 return a > r;
613}
614
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700615static int add_as_linear_device(struct dm_target *ti, char *dev)
616{
617 /*Move to linear mapping defines*/
Badhri Jagan Sridharan7e702182016-03-28 14:41:21 -0700618 char *linear_table_args[DM_LINEAR_ARGS] = {dev,
619 DM_LINEAR_TARGET_OFFSET};
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700620 int err = 0;
621
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700622 android_verity_target.dtr = dm_linear_dtr,
623 android_verity_target.map = dm_linear_map,
624 android_verity_target.status = dm_linear_status,
625 android_verity_target.ioctl = dm_linear_ioctl,
626 android_verity_target.merge = dm_linear_merge,
627 android_verity_target.iterate_devices = dm_linear_iterate_devices,
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700628 android_verity_target.io_hints = NULL;
629
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700630 err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700631
632 if (!err) {
633 DMINFO("Added android-verity as a linear target");
634 target_added = true;
635 } else
636 DMERR("Failed to add android-verity as linear target");
637
638 return err;
639}
640
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800641/*
642 * Target parameters:
643 * <key id> Key id of the public key in the system keyring.
644 * Verity metadata's signature would be verified against
645 * this. If the key id contains spaces, replace them
646 * with '#'.
647 * <block device> The block device for which dm-verity is being setup.
648 */
649static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
650{
651 dev_t uninitialized_var(dev);
652 struct android_metadata *uninitialized_var(metadata);
653 int err = 0, i, mode;
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700654 char *key_id, *table_ptr, dummy, *target_device,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800655 *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
656 /* One for specifying number of opt args and one for mode */
657 sector_t data_sectors;
658 u32 data_block_size;
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200659 unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800660 struct fec_header uninitialized_var(fec);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800661 struct fec_ecc_metadata uninitialized_var(ecc);
662 char buf[FEC_ARG_LENGTH], *buf_ptr;
663 unsigned long long tmpll;
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700664 u64 device_size;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800665
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700666 if (argc == 1) {
667 /* Use the default keyid */
668 if (default_verity_key_id())
669 key_id = veritykeyid;
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700670 else if (!is_eng()) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700671 DMERR("veritykeyid= is not set");
672 handle_error();
673 return -EINVAL;
674 }
675 } else if (argc == 2)
676 key_id = argv[1];
677 else {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800678 DMERR("Incorrect number of arguments");
679 handle_error();
680 return -EINVAL;
681 }
682
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700683 target_device = argv[0];
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800684
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700685 dev = name_to_dev_t(target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200686 if (!dev) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700687 DMERR("no dev found for %s", target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200688 handle_error();
689 return -EINVAL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800690 }
691
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700692 if (is_eng()) {
693 err = find_size(dev, &device_size);
694 if (err) {
695 DMERR("error finding bdev size");
696 handle_error();
697 return err;
698 }
699
700 ti->len = device_size;
701 err = add_as_linear_device(ti, target_device);
702 if (err) {
703 handle_error();
704 return err;
705 }
706 verity_enabled = false;
707 return 0;
708 }
709
710 strreplace(key_id, '#', ' ');
711
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700712 DMINFO("key:%s dev:%s", key_id, target_device);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800713
714 if (extract_fec_header(dev, &fec, &ecc)) {
715 DMERR("Error while extracting fec header");
716 handle_error();
717 return -EINVAL;
718 }
719
720 metadata = extract_metadata(dev, &fec);
721
722 if (IS_ERR(metadata)) {
723 DMERR("Error while extracting metadata");
724 handle_error();
725 return -EINVAL;
726 }
727
728 err = verify_header(metadata->header);
729
730 if (err == VERITY_STATE_DISABLE) {
731 DMERR("Mounting root with verity disabled");
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700732 verity_enabled = false;
733 /* we would still have to parse the args to figure out
734 * the data blocks size. Or may be could map the entire
735 * partition similar to mounting the device.
736 */
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800737 } else if (err) {
738 DMERR("Verity header handle error");
739 handle_error();
740 goto free_metadata;
741 }
742
Badhri Jagan Sridharane96affa2016-05-20 16:44:19 -0700743 if (verity_enabled) {
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700744 err = verify_verity_signature(key_id, metadata);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800745
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700746 if (err) {
747 DMERR("Signature verification failed");
748 handle_error();
749 goto free_metadata;
750 } else
751 DMINFO("Signature verification success");
752 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800753
754 table_ptr = metadata->verity_table;
755
756 for (i = 0; i < VERITY_TABLE_ARGS; i++) {
757 verity_table_args[i] = strsep(&table_ptr, " ");
758 if (verity_table_args[i] == NULL)
759 break;
760 }
761
762 if (i != VERITY_TABLE_ARGS) {
763 DMERR("Verity table not in the expected format");
764 err = -EINVAL;
765 handle_error();
766 goto free_metadata;
767 }
768
769 if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &dummy)
770 != 1) {
771 DMERR("Verity table not in the expected format");
772 handle_error();
773 err = -EINVAL;
774 goto free_metadata;
775 }
776
777 if (tmpll > ULONG_MAX) {
778 DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
779 handle_error();
780 err = -EINVAL;
781 goto free_metadata;
782 }
783
784 data_sectors = tmpll;
785
786 if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
787 != 1) {
788 DMERR("Verity table not in the expected format");
789 handle_error();
790 err = -EINVAL;
791 goto free_metadata;
792 }
793
794 if (test_mult_overflow(data_sectors, data_block_size >>
795 SECTOR_SHIFT)) {
796 DMERR("data_sectors too large");
797 handle_error();
798 err = -EOVERFLOW;
799 goto free_metadata;
800 }
801
802 data_sectors *= data_block_size >> SECTOR_SHIFT;
803 DMINFO("Data sectors %llu", (unsigned long long)data_sectors);
804
805 /* update target length */
806 ti->len = data_sectors;
807
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700808 /* Setup linear target and free */
809 if (!verity_enabled) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700810 err = add_as_linear_device(ti, target_device);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700811 goto free_metadata;
812 }
813
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800814 /*substitute data_dev and hash_dev*/
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700815 verity_table_args[1] = target_device;
816 verity_table_args[2] = target_device;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800817
818 mode = verity_mode();
819
820 if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
821 if (mode) {
822 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700823 "%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
824 1 + VERITY_TABLE_OPT_FEC_ARGS,
825 mode == DM_VERITY_MODE_RESTART ?
826 VERITY_TABLE_OPT_RESTART :
827 VERITY_TABLE_OPT_LOGGING,
828 target_device,
829 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
830 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800831 } else {
832 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700833 "%u " VERITY_TABLE_OPT_FEC_FORMAT,
834 VERITY_TABLE_OPT_FEC_ARGS, target_device,
835 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
836 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800837 }
838 } else if (mode) {
839 err = snprintf(buf, FEC_ARG_LENGTH,
840 "2 " VERITY_TABLE_OPT_IGNZERO " %s",
841 mode == DM_VERITY_MODE_RESTART ?
842 VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
843 } else {
844 err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
845 "ignore_zero_blocks");
846 }
847
848 if (err < 0 || err >= FEC_ARG_LENGTH)
849 goto free_metadata;
850
851 buf_ptr = buf;
852
853 for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
854 VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
855 verity_table_args[i] = strsep(&buf_ptr, " ");
856 if (verity_table_args[i] == NULL) {
857 no_of_args = i;
858 break;
859 }
860 }
861
862 err = verity_ctr(ti, no_of_args, verity_table_args);
863
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700864 if (err)
865 DMERR("android-verity failed to mount as verity target");
866 else {
867 target_added = true;
868 DMINFO("android-verity mounted as verity target");
869 }
870
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800871free_metadata:
872 kfree(metadata->header);
873 kfree(metadata->verity_table);
874 kfree(metadata);
875 return err;
876}
877
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800878static int __init dm_android_verity_init(void)
879{
880 int r;
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700881 struct dentry *file;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800882
883 r = dm_register_target(&android_verity_target);
884 if (r < 0)
885 DMERR("register failed %d", r);
886
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700887 /* Tracks the status of the last added target */
888 debug_dir = debugfs_create_dir("android_verity", NULL);
889
890 if (IS_ERR_OR_NULL(debug_dir)) {
891 DMERR("Cannot create android_verity debugfs directory: %ld",
892 PTR_ERR(debug_dir));
893 goto end;
894 }
895
896 file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
897 (u32 *)&target_added);
898
899 if (IS_ERR_OR_NULL(file)) {
900 DMERR("Cannot create android_verity debugfs directory: %ld",
901 PTR_ERR(debug_dir));
902 debugfs_remove_recursive(debug_dir);
903 goto end;
904 }
905
906 file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
907 (u32 *)&verity_enabled);
908
909 if (IS_ERR_OR_NULL(file)) {
910 DMERR("Cannot create android_verity debugfs directory: %ld",
911 PTR_ERR(debug_dir));
912 debugfs_remove_recursive(debug_dir);
913 }
914
915end:
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800916 return r;
917}
918
919static void __exit dm_android_verity_exit(void)
920{
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700921 if (!IS_ERR_OR_NULL(debug_dir))
922 debugfs_remove_recursive(debug_dir);
923
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800924 dm_unregister_target(&android_verity_target);
925}
926
927module_init(dm_android_verity_init);
928module_exit(dm_android_verity_exit);