blob: 881e7099d4012506c0939dfd412b392e8b56fa52 [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,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -070062 .prepare_ioctl = verity_prepare_ioctl,
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -070063 .iterate_devices = verity_iterate_devices,
64 .io_hints = verity_io_hints,
65};
66
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -080067static int __init verified_boot_state_param(char *line)
68{
69 strlcpy(verifiedbootstate, line, sizeof(verifiedbootstate));
70 return 1;
71}
72
73__setup("androidboot.verifiedbootstate=", verified_boot_state_param);
74
75static int __init verity_mode_param(char *line)
76{
77 strlcpy(veritymode, line, sizeof(veritymode));
78 return 1;
79}
80
81__setup("androidboot.veritymode=", verity_mode_param);
82
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -070083static int __init verity_keyid_param(char *line)
84{
85 strlcpy(veritykeyid, line, sizeof(veritykeyid));
86 return 1;
87}
88
89__setup("veritykeyid=", verity_keyid_param);
90
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -070091static int __init verity_buildvariant(char *line)
92{
93 strlcpy(buildvariant, line, sizeof(buildvariant));
94 return 1;
95}
96
97__setup("buildvariant=", verity_buildvariant);
98
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -070099static inline bool default_verity_key_id(void)
100{
101 return veritykeyid[0] != '\0';
102}
103
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700104static inline bool is_eng(void)
105{
106 static const char typeeng[] = "eng";
107
108 return !strncmp(buildvariant, typeeng, sizeof(typeeng));
109}
110
Badhri Jagan Sridharand5943e02016-06-27 16:25:55 -0700111static inline bool is_userdebug(void)
112{
113 static const char typeuserdebug[] = "userdebug";
114
115 return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
116}
117
118
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800119static int table_extract_mpi_array(struct public_key_signature *pks,
120 const void *data, size_t len)
121{
122 MPI mpi = mpi_read_raw_data(data, len);
123
124 if (!mpi) {
125 DMERR("Error while allocating mpi array");
126 return -ENOMEM;
127 }
128
129 pks->mpi[0] = mpi;
130 pks->nr_mpi = 1;
131 return 0;
132}
133
134static struct public_key_signature *table_make_digest(
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800135 enum hash_algo hash,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800136 const void *table,
137 unsigned long table_len)
138{
139 struct public_key_signature *pks = NULL;
140 struct crypto_shash *tfm;
141 struct shash_desc *desc;
142 size_t digest_size, desc_size;
143 int ret;
144
145 /* Allocate the hashing algorithm we're going to need and find out how
146 * big the hash operational data will be.
147 */
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800148 tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800149 if (IS_ERR(tfm))
150 return ERR_CAST(tfm);
151
152 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
153 digest_size = crypto_shash_digestsize(tfm);
154
155 /* We allocate the hash operational data storage on the end of out
156 * context data and the digest output buffer on the end of that.
157 */
158 ret = -ENOMEM;
159 pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
160 if (!pks)
161 goto error;
162
163 pks->pkey_hash_algo = hash;
164 pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
165 pks->digest_size = digest_size;
166
167 desc = (struct shash_desc *)(pks + 1);
168 desc->tfm = tfm;
169 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
170
171 ret = crypto_shash_init(desc);
172 if (ret < 0)
173 goto error;
174
175 ret = crypto_shash_finup(desc, table, table_len, pks->digest);
176 if (ret < 0)
177 goto error;
178
179 crypto_free_shash(tfm);
180 return pks;
181
182error:
183 kfree(pks);
184 crypto_free_shash(tfm);
185 return ERR_PTR(ret);
186}
187
188static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
189 sector_t offset, int length)
190{
191 struct bio *bio;
192 int err = 0, i;
193
194 payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);
195
196 bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
197 if (!bio) {
198 DMERR("Error while allocating bio");
199 return -ENOMEM;
200 }
201
202 bio->bi_bdev = bdev;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800203 bio->bi_iter.bi_sector = offset;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800204
205 payload->page_io = kzalloc(sizeof(struct page *) *
206 payload->number_of_pages, GFP_KERNEL);
207 if (!payload->page_io) {
208 DMERR("page_io array alloc failed");
209 err = -ENOMEM;
210 goto free_bio;
211 }
212
213 for (i = 0; i < payload->number_of_pages; i++) {
214 payload->page_io[i] = alloc_page(GFP_KERNEL);
215 if (!payload->page_io[i]) {
216 DMERR("alloc_page failed");
217 err = -ENOMEM;
218 goto free_pages;
219 }
220 if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
221 DMERR("bio_add_page error");
222 err = -EIO;
223 goto free_pages;
224 }
225 }
226
227 if (!submit_bio_wait(READ, bio))
228 /* success */
229 goto free_bio;
230 DMERR("bio read failed");
231 err = -EIO;
232
233free_pages:
234 for (i = 0; i < payload->number_of_pages; i++)
235 if (payload->page_io[i])
236 __free_page(payload->page_io[i]);
237 kfree(payload->page_io);
238free_bio:
239 bio_put(bio);
240 return err;
241}
242
243static inline u64 fec_div_round_up(u64 x, u64 y)
244{
245 u64 remainder;
246
247 return div64_u64_rem(x, y, &remainder) +
248 (remainder > 0 ? 1 : 0);
249}
250
251static inline void populate_fec_metadata(struct fec_header *header,
252 struct fec_ecc_metadata *ecc)
253{
254 ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
255 FEC_BLOCK_SIZE);
256 ecc->roots = le32_to_cpu(header->roots);
257 ecc->start = le64_to_cpu(header->inp_size);
258}
259
260static inline int validate_fec_header(struct fec_header *header, u64 offset)
261{
262 /* move offset to make the sanity check work for backup header
263 * as well. */
264 offset -= offset % FEC_BLOCK_SIZE;
265 if (le32_to_cpu(header->magic) != FEC_MAGIC ||
266 le32_to_cpu(header->version) != FEC_VERSION ||
267 le32_to_cpu(header->size) != sizeof(struct fec_header) ||
268 le32_to_cpu(header->roots) == 0 ||
Badhri Jagan Sridharan07bec5d2016-09-27 13:48:29 -0700269 le32_to_cpu(header->roots) >= FEC_RSM)
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800270 return -EINVAL;
271
272 return 0;
273}
274
275static int extract_fec_header(dev_t dev, struct fec_header *fec,
276 struct fec_ecc_metadata *ecc)
277{
278 u64 device_size;
279 struct bio_read payload;
280 int i, err = 0;
281 struct block_device *bdev;
282
283 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
284
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700285 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800286 DMERR("bdev get error");
287 return PTR_ERR(bdev);
288 }
289
290 device_size = i_size_read(bdev->bd_inode);
291
292 /* fec metadata size is a power of 2 and PAGE_SIZE
293 * is a power of 2 as well.
294 */
295 BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
296 /* 512 byte sector alignment */
297 BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);
298
299 err = read_block_dev(&payload, bdev, (device_size -
300 FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
301 if (err) {
302 DMERR("Error while reading verity metadata");
303 goto error;
304 }
305
306 BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
307 memcpy(fec, page_address(payload.page_io[0]),
308 sizeof(*fec));
309
310 ecc->valid = true;
311 if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
312 /* Try the backup header */
313 memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
314 - sizeof(*fec) ,
315 sizeof(*fec));
316 if (validate_fec_header(fec, device_size -
317 sizeof(struct fec_header)))
318 ecc->valid = false;
319 }
320
321 if (ecc->valid)
322 populate_fec_metadata(fec, ecc);
323
324 for (i = 0; i < payload.number_of_pages; i++)
325 __free_page(payload.page_io[i]);
326 kfree(payload.page_io);
327
328error:
329 blkdev_put(bdev, FMODE_READ);
330 return err;
331}
332static void find_metadata_offset(struct fec_header *fec,
333 struct block_device *bdev, u64 *metadata_offset)
334{
335 u64 device_size;
336
337 device_size = i_size_read(bdev->bd_inode);
338
339 if (le32_to_cpu(fec->magic) == FEC_MAGIC)
340 *metadata_offset = le64_to_cpu(fec->inp_size) -
341 VERITY_METADATA_SIZE;
342 else
343 *metadata_offset = device_size - VERITY_METADATA_SIZE;
344}
345
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700346static int find_size(dev_t dev, u64 *device_size)
347{
348 struct block_device *bdev;
349
350 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
351 if (IS_ERR_OR_NULL(bdev)) {
352 DMERR("blkdev_get_by_dev failed");
353 return PTR_ERR(bdev);
354 }
355
356 *device_size = i_size_read(bdev->bd_inode);
357 *device_size >>= SECTOR_SHIFT;
358
359 DMINFO("blkdev size in sectors: %llu", *device_size);
360 blkdev_put(bdev, FMODE_READ);
361 return 0;
362}
363
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700364static int verify_header(struct android_metadata_header *header)
365{
366 int retval = -EINVAL;
367
368 if (is_userdebug() && le32_to_cpu(header->magic_number) ==
369 VERITY_METADATA_MAGIC_DISABLE)
370 return VERITY_STATE_DISABLE;
371
372 if (!(le32_to_cpu(header->magic_number) ==
373 VERITY_METADATA_MAGIC_NUMBER) ||
374 (le32_to_cpu(header->magic_number) ==
375 VERITY_METADATA_MAGIC_DISABLE)) {
376 DMERR("Incorrect magic number");
377 return retval;
378 }
379
380 if (le32_to_cpu(header->protocol_version) !=
381 VERITY_METADATA_VERSION) {
382 DMERR("Unsupported version %u",
383 le32_to_cpu(header->protocol_version));
384 return retval;
385 }
386
387 return 0;
388}
389
390static int extract_metadata(dev_t dev, struct fec_header *fec,
391 struct android_metadata **metadata,
392 bool *verity_enabled)
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800393{
394 struct block_device *bdev;
395 struct android_metadata_header *header;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800396 int i;
397 u32 table_length, copy_length, offset;
398 u64 metadata_offset;
399 struct bio_read payload;
400 int err = 0;
401
402 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
403
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700404 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800405 DMERR("blkdev_get_by_dev failed");
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700406 return -ENODEV;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800407 }
408
409 find_metadata_offset(fec, bdev, &metadata_offset);
410
411 /* Verity metadata size is a power of 2 and PAGE_SIZE
412 * is a power of 2 as well.
413 * PAGE_SIZE is also a multiple of 512 bytes.
414 */
415 if (VERITY_METADATA_SIZE > PAGE_SIZE)
416 BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
417 /* 512 byte sector alignment */
418 BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);
419
420 err = read_block_dev(&payload, bdev, metadata_offset /
421 (1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
422 if (err) {
423 DMERR("Error while reading verity metadata");
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800424 goto blkdev_release;
425 }
426
427 header = kzalloc(sizeof(*header), GFP_KERNEL);
428 if (!header) {
429 DMERR("kzalloc failed for header");
430 err = -ENOMEM;
431 goto free_payload;
432 }
433
434 memcpy(header, page_address(payload.page_io[0]),
435 sizeof(*header));
436
437 DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
438 le32_to_cpu(header->magic_number),
439 le32_to_cpu(header->protocol_version),
440 le32_to_cpu(header->table_length));
441
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700442 err = verify_header(header);
443
444 if (err == VERITY_STATE_DISABLE) {
445 DMERR("Mounting root with verity disabled");
446 *verity_enabled = false;
447 /* we would still have to read the metadata to figure out
448 * the data blocks size. Or may be could map the entire
449 * partition similar to mounting the device.
450 *
451 * Reset error as well as the verity_enabled flag is changed.
452 */
453 err = 0;
454 } else if (err)
455 goto free_header;
456
457 *metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
458 if (!*metadata) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800459 DMERR("kzalloc for metadata failed");
460 err = -ENOMEM;
461 goto free_header;
462 }
463
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700464 (*metadata)->header = header;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800465 table_length = le32_to_cpu(header->table_length);
466
467 if (table_length == 0 ||
468 table_length > (VERITY_METADATA_SIZE -
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700469 sizeof(struct android_metadata_header))) {
470 DMERR("table_length too long");
471 err = -EINVAL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800472 goto free_metadata;
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700473 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800474
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700475 (*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800476
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700477 if (!(*metadata)->verity_table) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800478 DMERR("kzalloc verity_table failed");
479 err = -ENOMEM;
480 goto free_metadata;
481 }
482
483 if (sizeof(struct android_metadata_header) +
484 table_length <= PAGE_SIZE) {
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700485 memcpy((*metadata)->verity_table,
486 page_address(payload.page_io[0])
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800487 + sizeof(struct android_metadata_header),
488 table_length);
489 } else {
490 copy_length = PAGE_SIZE -
491 sizeof(struct android_metadata_header);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700492 memcpy((*metadata)->verity_table,
493 page_address(payload.page_io[0])
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800494 + sizeof(struct android_metadata_header),
495 copy_length);
496 table_length -= copy_length;
497 offset = copy_length;
498 i = 1;
499 while (table_length != 0) {
500 if (table_length > PAGE_SIZE) {
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700501 memcpy((*metadata)->verity_table + offset,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800502 page_address(payload.page_io[i]),
503 PAGE_SIZE);
504 offset += PAGE_SIZE;
505 table_length -= PAGE_SIZE;
506 } else {
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700507 memcpy((*metadata)->verity_table + offset,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800508 page_address(payload.page_io[i]),
509 table_length);
510 table_length = 0;
511 }
512 i++;
513 }
514 }
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700515 (*metadata)->verity_table[table_length] = '\0';
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800516
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700517 DMINFO("verity_table: %s", (*metadata)->verity_table);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800518 goto free_payload;
519
520free_metadata:
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700521 kfree(*metadata);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800522free_header:
523 kfree(header);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800524free_payload:
525 for (i = 0; i < payload.number_of_pages; i++)
526 if (payload.page_io[i])
527 __free_page(payload.page_io[i]);
528 kfree(payload.page_io);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800529blkdev_release:
530 blkdev_put(bdev, FMODE_READ);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700531 return err;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800532}
533
534/* helper functions to extract properties from dts */
535const char *find_dt_value(const char *name)
536{
537 struct device_node *firmware;
538 const char *value;
539
540 firmware = of_find_node_by_path("/firmware/android");
541 if (!firmware)
542 return NULL;
543 value = of_get_property(firmware, name, NULL);
544 of_node_put(firmware);
545
546 return value;
547}
548
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800549static int verity_mode(void)
550{
551 static const char enforcing[] = "enforcing";
552 static const char verified_mode_prop[] = "veritymode";
553 const char *value;
554
555 value = find_dt_value(verified_mode_prop);
556 if (!value)
557 value = veritymode;
558 if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
559 return DM_VERITY_MODE_RESTART;
560
561 return DM_VERITY_MODE_EIO;
562}
563
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800564static int verify_verity_signature(char *key_id,
565 struct android_metadata *metadata)
566{
567 key_ref_t key_ref;
568 struct key *key;
569 struct public_key_signature *pks = NULL;
570 int retval = -EINVAL;
571
572 key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1),
573 &key_type_asymmetric, key_id);
574
575 if (IS_ERR(key_ref)) {
576 DMERR("keyring: key not found");
577 return -ENOKEY;
578 }
579
580 key = key_ref_to_ptr(key_ref);
581
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800582 pks = table_make_digest(HASH_ALGO_SHA256,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800583 (const void *)metadata->verity_table,
584 le32_to_cpu(metadata->header->table_length));
585
586 if (IS_ERR(pks)) {
587 DMERR("hashing failed");
588 goto error;
589 }
590
591 retval = table_extract_mpi_array(pks, &metadata->header->signature[0],
592 RSANUMBYTES);
593 if (retval < 0) {
594 DMERR("Error extracting mpi %d", retval);
595 goto error;
596 }
597
598 retval = verify_signature(key, pks);
599 mpi_free(pks->rsa.s);
600error:
601 kfree(pks);
602 key_put(key);
603
604 return retval;
605}
606
607static void handle_error(void)
608{
609 int mode = verity_mode();
610 if (mode == DM_VERITY_MODE_RESTART) {
611 DMERR("triggering restart");
612 kernel_restart("dm-verity device corrupted");
613 } else {
614 DMERR("Mounting verity root failed");
615 }
616}
617
618static inline bool test_mult_overflow(sector_t a, u32 b)
619{
620 sector_t r = (sector_t)~0ULL;
621
622 sector_div(r, b);
623 return a > r;
624}
625
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700626static int add_as_linear_device(struct dm_target *ti, char *dev)
627{
628 /*Move to linear mapping defines*/
Badhri Jagan Sridharan7e702182016-03-28 14:41:21 -0700629 char *linear_table_args[DM_LINEAR_ARGS] = {dev,
630 DM_LINEAR_TARGET_OFFSET};
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700631 int err = 0;
632
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700633 android_verity_target.dtr = dm_linear_dtr,
634 android_verity_target.map = dm_linear_map,
635 android_verity_target.status = dm_linear_status,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700636 android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700637 android_verity_target.iterate_devices = dm_linear_iterate_devices,
Badhri Jagan Sridharanc5b8dcd2017-01-13 11:05:00 -0800638 android_verity_target.direct_access = dm_linear_direct_access,
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700639 android_verity_target.io_hints = NULL;
640
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700641 err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700642
643 if (!err) {
644 DMINFO("Added android-verity as a linear target");
645 target_added = true;
646 } else
647 DMERR("Failed to add android-verity as linear target");
648
649 return err;
650}
651
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800652/*
653 * Target parameters:
654 * <key id> Key id of the public key in the system keyring.
655 * Verity metadata's signature would be verified against
656 * this. If the key id contains spaces, replace them
657 * with '#'.
658 * <block device> The block device for which dm-verity is being setup.
659 */
660static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
661{
662 dev_t uninitialized_var(dev);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700663 struct android_metadata *metadata = NULL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800664 int err = 0, i, mode;
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700665 char *key_id, *table_ptr, dummy, *target_device,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800666 *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
667 /* One for specifying number of opt args and one for mode */
668 sector_t data_sectors;
669 u32 data_block_size;
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200670 unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800671 struct fec_header uninitialized_var(fec);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800672 struct fec_ecc_metadata uninitialized_var(ecc);
673 char buf[FEC_ARG_LENGTH], *buf_ptr;
674 unsigned long long tmpll;
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700675 u64 uninitialized_var(device_size);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800676
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700677 if (argc == 1) {
678 /* Use the default keyid */
679 if (default_verity_key_id())
680 key_id = veritykeyid;
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700681 else if (!is_eng()) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700682 DMERR("veritykeyid= is not set");
683 handle_error();
684 return -EINVAL;
685 }
686 } else if (argc == 2)
687 key_id = argv[1];
688 else {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800689 DMERR("Incorrect number of arguments");
690 handle_error();
691 return -EINVAL;
692 }
693
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700694 target_device = argv[0];
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800695
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700696 dev = name_to_dev_t(target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200697 if (!dev) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700698 DMERR("no dev found for %s", target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200699 handle_error();
700 return -EINVAL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800701 }
702
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700703 if (is_eng()) {
704 err = find_size(dev, &device_size);
705 if (err) {
706 DMERR("error finding bdev size");
707 handle_error();
708 return err;
709 }
710
711 ti->len = device_size;
712 err = add_as_linear_device(ti, target_device);
713 if (err) {
714 handle_error();
715 return err;
716 }
717 verity_enabled = false;
718 return 0;
719 }
720
721 strreplace(key_id, '#', ' ');
722
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700723 DMINFO("key:%s dev:%s", key_id, target_device);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800724
725 if (extract_fec_header(dev, &fec, &ecc)) {
726 DMERR("Error while extracting fec header");
727 handle_error();
728 return -EINVAL;
729 }
730
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700731 err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800732
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700733 if (err) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800734 DMERR("Error while extracting metadata");
735 handle_error();
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800736 goto free_metadata;
737 }
738
Badhri Jagan Sridharane96affa2016-05-20 16:44:19 -0700739 if (verity_enabled) {
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700740 err = verify_verity_signature(key_id, metadata);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800741
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700742 if (err) {
743 DMERR("Signature verification failed");
744 handle_error();
745 goto free_metadata;
746 } else
747 DMINFO("Signature verification success");
748 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800749
750 table_ptr = metadata->verity_table;
751
752 for (i = 0; i < VERITY_TABLE_ARGS; i++) {
753 verity_table_args[i] = strsep(&table_ptr, " ");
754 if (verity_table_args[i] == NULL)
755 break;
756 }
757
758 if (i != VERITY_TABLE_ARGS) {
759 DMERR("Verity table not in the expected format");
760 err = -EINVAL;
761 handle_error();
762 goto free_metadata;
763 }
764
765 if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &dummy)
766 != 1) {
767 DMERR("Verity table not in the expected format");
768 handle_error();
769 err = -EINVAL;
770 goto free_metadata;
771 }
772
773 if (tmpll > ULONG_MAX) {
774 DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
775 handle_error();
776 err = -EINVAL;
777 goto free_metadata;
778 }
779
780 data_sectors = tmpll;
781
782 if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
783 != 1) {
784 DMERR("Verity table not in the expected format");
785 handle_error();
786 err = -EINVAL;
787 goto free_metadata;
788 }
789
790 if (test_mult_overflow(data_sectors, data_block_size >>
791 SECTOR_SHIFT)) {
792 DMERR("data_sectors too large");
793 handle_error();
794 err = -EOVERFLOW;
795 goto free_metadata;
796 }
797
798 data_sectors *= data_block_size >> SECTOR_SHIFT;
799 DMINFO("Data sectors %llu", (unsigned long long)data_sectors);
800
801 /* update target length */
802 ti->len = data_sectors;
803
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700804 /* Setup linear target and free */
805 if (!verity_enabled) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700806 err = add_as_linear_device(ti, target_device);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700807 goto free_metadata;
808 }
809
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800810 /*substitute data_dev and hash_dev*/
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700811 verity_table_args[1] = target_device;
812 verity_table_args[2] = target_device;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800813
814 mode = verity_mode();
815
816 if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
817 if (mode) {
818 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700819 "%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
820 1 + VERITY_TABLE_OPT_FEC_ARGS,
821 mode == DM_VERITY_MODE_RESTART ?
822 VERITY_TABLE_OPT_RESTART :
823 VERITY_TABLE_OPT_LOGGING,
824 target_device,
825 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
826 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800827 } else {
828 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700829 "%u " VERITY_TABLE_OPT_FEC_FORMAT,
830 VERITY_TABLE_OPT_FEC_ARGS, target_device,
831 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
832 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800833 }
834 } else if (mode) {
835 err = snprintf(buf, FEC_ARG_LENGTH,
836 "2 " VERITY_TABLE_OPT_IGNZERO " %s",
837 mode == DM_VERITY_MODE_RESTART ?
838 VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
839 } else {
840 err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
841 "ignore_zero_blocks");
842 }
843
844 if (err < 0 || err >= FEC_ARG_LENGTH)
845 goto free_metadata;
846
847 buf_ptr = buf;
848
849 for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
850 VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
851 verity_table_args[i] = strsep(&buf_ptr, " ");
852 if (verity_table_args[i] == NULL) {
853 no_of_args = i;
854 break;
855 }
856 }
857
858 err = verity_ctr(ti, no_of_args, verity_table_args);
859
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700860 if (err)
861 DMERR("android-verity failed to mount as verity target");
862 else {
863 target_added = true;
864 DMINFO("android-verity mounted as verity target");
865 }
866
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800867free_metadata:
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700868 if (metadata) {
869 kfree(metadata->header);
870 kfree(metadata->verity_table);
871 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800872 kfree(metadata);
873 return err;
874}
875
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800876static int __init dm_android_verity_init(void)
877{
878 int r;
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700879 struct dentry *file;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800880
881 r = dm_register_target(&android_verity_target);
882 if (r < 0)
883 DMERR("register failed %d", r);
884
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700885 /* Tracks the status of the last added target */
886 debug_dir = debugfs_create_dir("android_verity", NULL);
887
888 if (IS_ERR_OR_NULL(debug_dir)) {
889 DMERR("Cannot create android_verity debugfs directory: %ld",
890 PTR_ERR(debug_dir));
891 goto end;
892 }
893
894 file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700895 &target_added);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700896
897 if (IS_ERR_OR_NULL(file)) {
898 DMERR("Cannot create android_verity debugfs directory: %ld",
899 PTR_ERR(debug_dir));
900 debugfs_remove_recursive(debug_dir);
901 goto end;
902 }
903
904 file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700905 &verity_enabled);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700906
907 if (IS_ERR_OR_NULL(file)) {
908 DMERR("Cannot create android_verity debugfs directory: %ld",
909 PTR_ERR(debug_dir));
910 debugfs_remove_recursive(debug_dir);
911 }
912
913end:
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800914 return r;
915}
916
917static void __exit dm_android_verity_exit(void)
918{
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700919 if (!IS_ERR_OR_NULL(debug_dir))
920 debugfs_remove_recursive(debug_dir);
921
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800922 dm_unregister_target(&android_verity_target);
923}
924
925module_init(dm_android_verity_init);
926module_exit(dm_android_verity_exit);