blob: eb4bdf66087cf195f5b9b8005bac23829223efbf [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
Bowgo Tsai80f190c2017-03-02 18:54:15 +0800118static inline bool is_unlocked(void)
119{
120 static const char unlocked[] = "orange";
121
122 return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked));
123}
Badhri Jagan Sridharand5943e02016-06-27 16:25:55 -0700124
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800125static int table_extract_mpi_array(struct public_key_signature *pks,
126 const void *data, size_t len)
127{
128 MPI mpi = mpi_read_raw_data(data, len);
129
130 if (!mpi) {
131 DMERR("Error while allocating mpi array");
132 return -ENOMEM;
133 }
134
135 pks->mpi[0] = mpi;
136 pks->nr_mpi = 1;
137 return 0;
138}
139
140static struct public_key_signature *table_make_digest(
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800141 enum hash_algo hash,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800142 const void *table,
143 unsigned long table_len)
144{
145 struct public_key_signature *pks = NULL;
146 struct crypto_shash *tfm;
147 struct shash_desc *desc;
148 size_t digest_size, desc_size;
149 int ret;
150
151 /* Allocate the hashing algorithm we're going to need and find out how
152 * big the hash operational data will be.
153 */
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800154 tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800155 if (IS_ERR(tfm))
156 return ERR_CAST(tfm);
157
158 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
159 digest_size = crypto_shash_digestsize(tfm);
160
161 /* We allocate the hash operational data storage on the end of out
162 * context data and the digest output buffer on the end of that.
163 */
164 ret = -ENOMEM;
165 pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
166 if (!pks)
167 goto error;
168
169 pks->pkey_hash_algo = hash;
170 pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
171 pks->digest_size = digest_size;
172
173 desc = (struct shash_desc *)(pks + 1);
174 desc->tfm = tfm;
175 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
176
177 ret = crypto_shash_init(desc);
178 if (ret < 0)
179 goto error;
180
181 ret = crypto_shash_finup(desc, table, table_len, pks->digest);
182 if (ret < 0)
183 goto error;
184
185 crypto_free_shash(tfm);
186 return pks;
187
188error:
189 kfree(pks);
190 crypto_free_shash(tfm);
191 return ERR_PTR(ret);
192}
193
194static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
195 sector_t offset, int length)
196{
197 struct bio *bio;
198 int err = 0, i;
199
200 payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);
201
202 bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
203 if (!bio) {
204 DMERR("Error while allocating bio");
205 return -ENOMEM;
206 }
207
208 bio->bi_bdev = bdev;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800209 bio->bi_iter.bi_sector = offset;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800210
211 payload->page_io = kzalloc(sizeof(struct page *) *
212 payload->number_of_pages, GFP_KERNEL);
213 if (!payload->page_io) {
214 DMERR("page_io array alloc failed");
215 err = -ENOMEM;
216 goto free_bio;
217 }
218
219 for (i = 0; i < payload->number_of_pages; i++) {
220 payload->page_io[i] = alloc_page(GFP_KERNEL);
221 if (!payload->page_io[i]) {
222 DMERR("alloc_page failed");
223 err = -ENOMEM;
224 goto free_pages;
225 }
226 if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
227 DMERR("bio_add_page error");
228 err = -EIO;
229 goto free_pages;
230 }
231 }
232
233 if (!submit_bio_wait(READ, bio))
234 /* success */
235 goto free_bio;
236 DMERR("bio read failed");
237 err = -EIO;
238
239free_pages:
240 for (i = 0; i < payload->number_of_pages; i++)
241 if (payload->page_io[i])
242 __free_page(payload->page_io[i]);
243 kfree(payload->page_io);
244free_bio:
245 bio_put(bio);
246 return err;
247}
248
249static inline u64 fec_div_round_up(u64 x, u64 y)
250{
251 u64 remainder;
252
253 return div64_u64_rem(x, y, &remainder) +
254 (remainder > 0 ? 1 : 0);
255}
256
257static inline void populate_fec_metadata(struct fec_header *header,
258 struct fec_ecc_metadata *ecc)
259{
260 ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
261 FEC_BLOCK_SIZE);
262 ecc->roots = le32_to_cpu(header->roots);
263 ecc->start = le64_to_cpu(header->inp_size);
264}
265
266static inline int validate_fec_header(struct fec_header *header, u64 offset)
267{
268 /* move offset to make the sanity check work for backup header
269 * as well. */
270 offset -= offset % FEC_BLOCK_SIZE;
271 if (le32_to_cpu(header->magic) != FEC_MAGIC ||
272 le32_to_cpu(header->version) != FEC_VERSION ||
273 le32_to_cpu(header->size) != sizeof(struct fec_header) ||
274 le32_to_cpu(header->roots) == 0 ||
Badhri Jagan Sridharan07bec5d2016-09-27 13:48:29 -0700275 le32_to_cpu(header->roots) >= FEC_RSM)
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800276 return -EINVAL;
277
278 return 0;
279}
280
281static int extract_fec_header(dev_t dev, struct fec_header *fec,
282 struct fec_ecc_metadata *ecc)
283{
284 u64 device_size;
285 struct bio_read payload;
286 int i, err = 0;
287 struct block_device *bdev;
288
289 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
290
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700291 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800292 DMERR("bdev get error");
293 return PTR_ERR(bdev);
294 }
295
296 device_size = i_size_read(bdev->bd_inode);
297
298 /* fec metadata size is a power of 2 and PAGE_SIZE
299 * is a power of 2 as well.
300 */
301 BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
302 /* 512 byte sector alignment */
303 BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);
304
305 err = read_block_dev(&payload, bdev, (device_size -
306 FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
307 if (err) {
308 DMERR("Error while reading verity metadata");
309 goto error;
310 }
311
312 BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
313 memcpy(fec, page_address(payload.page_io[0]),
314 sizeof(*fec));
315
316 ecc->valid = true;
317 if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
318 /* Try the backup header */
319 memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
320 - sizeof(*fec) ,
321 sizeof(*fec));
322 if (validate_fec_header(fec, device_size -
323 sizeof(struct fec_header)))
324 ecc->valid = false;
325 }
326
327 if (ecc->valid)
328 populate_fec_metadata(fec, ecc);
329
330 for (i = 0; i < payload.number_of_pages; i++)
331 __free_page(payload.page_io[i]);
332 kfree(payload.page_io);
333
334error:
335 blkdev_put(bdev, FMODE_READ);
336 return err;
337}
338static void find_metadata_offset(struct fec_header *fec,
339 struct block_device *bdev, u64 *metadata_offset)
340{
341 u64 device_size;
342
343 device_size = i_size_read(bdev->bd_inode);
344
345 if (le32_to_cpu(fec->magic) == FEC_MAGIC)
346 *metadata_offset = le64_to_cpu(fec->inp_size) -
347 VERITY_METADATA_SIZE;
348 else
349 *metadata_offset = device_size - VERITY_METADATA_SIZE;
350}
351
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700352static int find_size(dev_t dev, u64 *device_size)
353{
354 struct block_device *bdev;
355
356 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
357 if (IS_ERR_OR_NULL(bdev)) {
358 DMERR("blkdev_get_by_dev failed");
359 return PTR_ERR(bdev);
360 }
361
362 *device_size = i_size_read(bdev->bd_inode);
363 *device_size >>= SECTOR_SHIFT;
364
365 DMINFO("blkdev size in sectors: %llu", *device_size);
366 blkdev_put(bdev, FMODE_READ);
367 return 0;
368}
369
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700370static int verify_header(struct android_metadata_header *header)
371{
372 int retval = -EINVAL;
373
374 if (is_userdebug() && le32_to_cpu(header->magic_number) ==
375 VERITY_METADATA_MAGIC_DISABLE)
376 return VERITY_STATE_DISABLE;
377
378 if (!(le32_to_cpu(header->magic_number) ==
379 VERITY_METADATA_MAGIC_NUMBER) ||
380 (le32_to_cpu(header->magic_number) ==
381 VERITY_METADATA_MAGIC_DISABLE)) {
382 DMERR("Incorrect magic number");
383 return retval;
384 }
385
386 if (le32_to_cpu(header->protocol_version) !=
387 VERITY_METADATA_VERSION) {
388 DMERR("Unsupported version %u",
389 le32_to_cpu(header->protocol_version));
390 return retval;
391 }
392
393 return 0;
394}
395
396static int extract_metadata(dev_t dev, struct fec_header *fec,
397 struct android_metadata **metadata,
398 bool *verity_enabled)
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800399{
400 struct block_device *bdev;
401 struct android_metadata_header *header;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800402 int i;
403 u32 table_length, copy_length, offset;
404 u64 metadata_offset;
405 struct bio_read payload;
406 int err = 0;
407
408 bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
409
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700410 if (IS_ERR_OR_NULL(bdev)) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800411 DMERR("blkdev_get_by_dev failed");
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700412 return -ENODEV;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800413 }
414
415 find_metadata_offset(fec, bdev, &metadata_offset);
416
417 /* Verity metadata size is a power of 2 and PAGE_SIZE
418 * is a power of 2 as well.
419 * PAGE_SIZE is also a multiple of 512 bytes.
420 */
421 if (VERITY_METADATA_SIZE > PAGE_SIZE)
422 BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
423 /* 512 byte sector alignment */
424 BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);
425
426 err = read_block_dev(&payload, bdev, metadata_offset /
427 (1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
428 if (err) {
429 DMERR("Error while reading verity metadata");
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800430 goto blkdev_release;
431 }
432
433 header = kzalloc(sizeof(*header), GFP_KERNEL);
434 if (!header) {
435 DMERR("kzalloc failed for header");
436 err = -ENOMEM;
437 goto free_payload;
438 }
439
440 memcpy(header, page_address(payload.page_io[0]),
441 sizeof(*header));
442
443 DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
444 le32_to_cpu(header->magic_number),
445 le32_to_cpu(header->protocol_version),
446 le32_to_cpu(header->table_length));
447
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700448 err = verify_header(header);
449
450 if (err == VERITY_STATE_DISABLE) {
451 DMERR("Mounting root with verity disabled");
452 *verity_enabled = false;
453 /* we would still have to read the metadata to figure out
454 * the data blocks size. Or may be could map the entire
455 * partition similar to mounting the device.
456 *
457 * Reset error as well as the verity_enabled flag is changed.
458 */
459 err = 0;
460 } else if (err)
461 goto free_header;
462
463 *metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
464 if (!*metadata) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800465 DMERR("kzalloc for metadata failed");
466 err = -ENOMEM;
467 goto free_header;
468 }
469
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700470 (*metadata)->header = header;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800471 table_length = le32_to_cpu(header->table_length);
472
473 if (table_length == 0 ||
474 table_length > (VERITY_METADATA_SIZE -
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700475 sizeof(struct android_metadata_header))) {
476 DMERR("table_length too long");
477 err = -EINVAL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800478 goto free_metadata;
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700479 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800480
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700481 (*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800482
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700483 if (!(*metadata)->verity_table) {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800484 DMERR("kzalloc verity_table failed");
485 err = -ENOMEM;
486 goto free_metadata;
487 }
488
489 if (sizeof(struct android_metadata_header) +
490 table_length <= PAGE_SIZE) {
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700491 memcpy((*metadata)->verity_table,
492 page_address(payload.page_io[0])
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800493 + sizeof(struct android_metadata_header),
494 table_length);
495 } else {
496 copy_length = PAGE_SIZE -
497 sizeof(struct android_metadata_header);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700498 memcpy((*metadata)->verity_table,
499 page_address(payload.page_io[0])
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800500 + sizeof(struct android_metadata_header),
501 copy_length);
502 table_length -= copy_length;
503 offset = copy_length;
504 i = 1;
505 while (table_length != 0) {
506 if (table_length > PAGE_SIZE) {
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 PAGE_SIZE);
510 offset += PAGE_SIZE;
511 table_length -= PAGE_SIZE;
512 } else {
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700513 memcpy((*metadata)->verity_table + offset,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800514 page_address(payload.page_io[i]),
515 table_length);
516 table_length = 0;
517 }
518 i++;
519 }
520 }
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700521 (*metadata)->verity_table[table_length] = '\0';
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800522
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700523 DMINFO("verity_table: %s", (*metadata)->verity_table);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800524 goto free_payload;
525
526free_metadata:
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700527 kfree(*metadata);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800528free_header:
529 kfree(header);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800530free_payload:
531 for (i = 0; i < payload.number_of_pages; i++)
532 if (payload.page_io[i])
533 __free_page(payload.page_io[i]);
534 kfree(payload.page_io);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800535blkdev_release:
536 blkdev_put(bdev, FMODE_READ);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700537 return err;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800538}
539
540/* helper functions to extract properties from dts */
541const char *find_dt_value(const char *name)
542{
543 struct device_node *firmware;
544 const char *value;
545
546 firmware = of_find_node_by_path("/firmware/android");
547 if (!firmware)
548 return NULL;
549 value = of_get_property(firmware, name, NULL);
550 of_node_put(firmware);
551
552 return value;
553}
554
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800555static int verity_mode(void)
556{
557 static const char enforcing[] = "enforcing";
558 static const char verified_mode_prop[] = "veritymode";
559 const char *value;
560
561 value = find_dt_value(verified_mode_prop);
562 if (!value)
563 value = veritymode;
564 if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
565 return DM_VERITY_MODE_RESTART;
566
567 return DM_VERITY_MODE_EIO;
568}
569
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800570static int verify_verity_signature(char *key_id,
571 struct android_metadata *metadata)
572{
573 key_ref_t key_ref;
574 struct key *key;
575 struct public_key_signature *pks = NULL;
576 int retval = -EINVAL;
577
578 key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1),
579 &key_type_asymmetric, key_id);
580
581 if (IS_ERR(key_ref)) {
582 DMERR("keyring: key not found");
583 return -ENOKEY;
584 }
585
586 key = key_ref_to_ptr(key_ref);
587
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800588 pks = table_make_digest(HASH_ALGO_SHA256,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800589 (const void *)metadata->verity_table,
590 le32_to_cpu(metadata->header->table_length));
591
592 if (IS_ERR(pks)) {
593 DMERR("hashing failed");
Greg Hackmannd3196602016-11-14 09:48:02 -0800594 retval = PTR_ERR(pks);
595 pks = NULL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800596 goto error;
597 }
598
599 retval = table_extract_mpi_array(pks, &metadata->header->signature[0],
600 RSANUMBYTES);
601 if (retval < 0) {
602 DMERR("Error extracting mpi %d", retval);
603 goto error;
604 }
605
606 retval = verify_signature(key, pks);
607 mpi_free(pks->rsa.s);
608error:
609 kfree(pks);
610 key_put(key);
611
612 return retval;
613}
614
615static void handle_error(void)
616{
617 int mode = verity_mode();
618 if (mode == DM_VERITY_MODE_RESTART) {
619 DMERR("triggering restart");
620 kernel_restart("dm-verity device corrupted");
621 } else {
622 DMERR("Mounting verity root failed");
623 }
624}
625
626static inline bool test_mult_overflow(sector_t a, u32 b)
627{
628 sector_t r = (sector_t)~0ULL;
629
630 sector_div(r, b);
631 return a > r;
632}
633
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700634static int add_as_linear_device(struct dm_target *ti, char *dev)
635{
636 /*Move to linear mapping defines*/
Badhri Jagan Sridharan7e702182016-03-28 14:41:21 -0700637 char *linear_table_args[DM_LINEAR_ARGS] = {dev,
638 DM_LINEAR_TARGET_OFFSET};
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700639 int err = 0;
640
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700641 android_verity_target.dtr = dm_linear_dtr,
642 android_verity_target.map = dm_linear_map,
643 android_verity_target.status = dm_linear_status,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700644 android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700645 android_verity_target.iterate_devices = dm_linear_iterate_devices,
Badhri Jagan Sridharanc5b8dcd2017-01-13 11:05:00 -0800646 android_verity_target.direct_access = dm_linear_direct_access,
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700647 android_verity_target.io_hints = NULL;
648
Badhri Jagan Sridharanc4676ff2016-06-03 13:16:59 -0700649 set_disk_ro(dm_disk(dm_table_get_md(ti->table)), 0);
650
Badhri Jagan Sridharan67584ff2016-04-05 11:18:16 -0700651 err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700652
653 if (!err) {
654 DMINFO("Added android-verity as a linear target");
655 target_added = true;
656 } else
657 DMERR("Failed to add android-verity as linear target");
658
659 return err;
660}
661
Bowgo Tsai80f190c2017-03-02 18:54:15 +0800662static int create_linear_device(struct dm_target *ti, dev_t dev,
663 char *target_device)
664{
665 u64 device_size = 0;
666 int err = find_size(dev, &device_size);
667
668 if (err) {
669 DMERR("error finding bdev size");
670 handle_error();
671 return err;
672 }
673
674 ti->len = device_size;
675 err = add_as_linear_device(ti, target_device);
676 if (err) {
677 handle_error();
678 return err;
679 }
680 verity_enabled = false;
681 return 0;
682}
683
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800684/*
685 * Target parameters:
686 * <key id> Key id of the public key in the system keyring.
687 * Verity metadata's signature would be verified against
688 * this. If the key id contains spaces, replace them
689 * with '#'.
690 * <block device> The block device for which dm-verity is being setup.
691 */
692static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
693{
694 dev_t uninitialized_var(dev);
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700695 struct android_metadata *metadata = NULL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800696 int err = 0, i, mode;
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700697 char *key_id, *table_ptr, dummy, *target_device,
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800698 *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
699 /* One for specifying number of opt args and one for mode */
700 sector_t data_sectors;
701 u32 data_block_size;
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200702 unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
Badhri Jagan Sridharan56f6a6b2016-02-08 16:28:43 -0800703 struct fec_header uninitialized_var(fec);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800704 struct fec_ecc_metadata uninitialized_var(ecc);
705 char buf[FEC_ARG_LENGTH], *buf_ptr;
706 unsigned long long tmpll;
707
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700708 if (argc == 1) {
709 /* Use the default keyid */
710 if (default_verity_key_id())
711 key_id = veritykeyid;
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700712 else if (!is_eng()) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700713 DMERR("veritykeyid= is not set");
714 handle_error();
715 return -EINVAL;
716 }
717 } else if (argc == 2)
718 key_id = argv[1];
719 else {
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800720 DMERR("Incorrect number of arguments");
721 handle_error();
722 return -EINVAL;
723 }
724
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700725 target_device = argv[0];
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800726
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700727 dev = name_to_dev_t(target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200728 if (!dev) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700729 DMERR("no dev found for %s", target_device);
Jeremy Compostella0b768a42016-04-15 13:32:54 +0200730 handle_error();
731 return -EINVAL;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800732 }
733
Bowgo Tsai80f190c2017-03-02 18:54:15 +0800734 if (is_eng())
735 return create_linear_device(ti, dev, target_device);
Badhri Jagan Sridharanc68a6152016-06-17 18:54:35 -0700736
737 strreplace(key_id, '#', ' ');
738
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700739 DMINFO("key:%s dev:%s", key_id, target_device);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800740
741 if (extract_fec_header(dev, &fec, &ecc)) {
742 DMERR("Error while extracting fec header");
743 handle_error();
744 return -EINVAL;
745 }
746
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700747 err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800748
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700749 if (err) {
Bowgo Tsai80f190c2017-03-02 18:54:15 +0800750 /* Allow invalid metadata when the device is unlocked */
751 if (is_unlocked()) {
752 DMWARN("Allow invalid metadata when unlocked");
753 return create_linear_device(ti, dev, target_device);
754 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800755 DMERR("Error while extracting metadata");
756 handle_error();
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800757 goto free_metadata;
758 }
759
Badhri Jagan Sridharane96affa2016-05-20 16:44:19 -0700760 if (verity_enabled) {
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700761 err = verify_verity_signature(key_id, metadata);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800762
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700763 if (err) {
764 DMERR("Signature verification failed");
765 handle_error();
766 goto free_metadata;
767 } else
768 DMINFO("Signature verification success");
769 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800770
771 table_ptr = metadata->verity_table;
772
773 for (i = 0; i < VERITY_TABLE_ARGS; i++) {
774 verity_table_args[i] = strsep(&table_ptr, " ");
775 if (verity_table_args[i] == NULL)
776 break;
777 }
778
779 if (i != VERITY_TABLE_ARGS) {
780 DMERR("Verity table not in the expected format");
781 err = -EINVAL;
782 handle_error();
783 goto free_metadata;
784 }
785
786 if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &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 (tmpll > ULONG_MAX) {
795 DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
796 handle_error();
797 err = -EINVAL;
798 goto free_metadata;
799 }
800
801 data_sectors = tmpll;
802
803 if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
804 != 1) {
805 DMERR("Verity table not in the expected format");
806 handle_error();
807 err = -EINVAL;
808 goto free_metadata;
809 }
810
811 if (test_mult_overflow(data_sectors, data_block_size >>
812 SECTOR_SHIFT)) {
813 DMERR("data_sectors too large");
814 handle_error();
815 err = -EOVERFLOW;
816 goto free_metadata;
817 }
818
819 data_sectors *= data_block_size >> SECTOR_SHIFT;
820 DMINFO("Data sectors %llu", (unsigned long long)data_sectors);
821
822 /* update target length */
823 ti->len = data_sectors;
824
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700825 /* Setup linear target and free */
826 if (!verity_enabled) {
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700827 err = add_as_linear_device(ti, target_device);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700828 goto free_metadata;
829 }
830
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800831 /*substitute data_dev and hash_dev*/
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700832 verity_table_args[1] = target_device;
833 verity_table_args[2] = target_device;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800834
835 mode = verity_mode();
836
837 if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
838 if (mode) {
839 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700840 "%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
841 1 + VERITY_TABLE_OPT_FEC_ARGS,
842 mode == DM_VERITY_MODE_RESTART ?
843 VERITY_TABLE_OPT_RESTART :
844 VERITY_TABLE_OPT_LOGGING,
845 target_device,
846 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
847 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800848 } else {
849 err = snprintf(buf, FEC_ARG_LENGTH,
Badhri Jagan Sridharanadb82b92016-05-20 16:45:45 -0700850 "%u " VERITY_TABLE_OPT_FEC_FORMAT,
851 VERITY_TABLE_OPT_FEC_ARGS, target_device,
852 ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
853 ecc.roots);
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800854 }
855 } else if (mode) {
856 err = snprintf(buf, FEC_ARG_LENGTH,
857 "2 " VERITY_TABLE_OPT_IGNZERO " %s",
858 mode == DM_VERITY_MODE_RESTART ?
859 VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
860 } else {
861 err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
862 "ignore_zero_blocks");
863 }
864
865 if (err < 0 || err >= FEC_ARG_LENGTH)
866 goto free_metadata;
867
868 buf_ptr = buf;
869
870 for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
871 VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
872 verity_table_args[i] = strsep(&buf_ptr, " ");
873 if (verity_table_args[i] == NULL) {
874 no_of_args = i;
875 break;
876 }
877 }
878
879 err = verity_ctr(ti, no_of_args, verity_table_args);
880
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700881 if (err)
882 DMERR("android-verity failed to mount as verity target");
883 else {
884 target_added = true;
885 DMINFO("android-verity mounted as verity target");
886 }
887
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800888free_metadata:
Badhri Jagan Sridharan76350642016-07-06 17:16:19 -0700889 if (metadata) {
890 kfree(metadata->header);
891 kfree(metadata->verity_table);
892 }
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800893 kfree(metadata);
894 return err;
895}
896
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800897static int __init dm_android_verity_init(void)
898{
899 int r;
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700900 struct dentry *file;
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800901
902 r = dm_register_target(&android_verity_target);
903 if (r < 0)
904 DMERR("register failed %d", r);
905
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700906 /* Tracks the status of the last added target */
907 debug_dir = debugfs_create_dir("android_verity", NULL);
908
909 if (IS_ERR_OR_NULL(debug_dir)) {
910 DMERR("Cannot create android_verity debugfs directory: %ld",
911 PTR_ERR(debug_dir));
912 goto end;
913 }
914
915 file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700916 &target_added);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700917
918 if (IS_ERR_OR_NULL(file)) {
919 DMERR("Cannot create android_verity debugfs directory: %ld",
920 PTR_ERR(debug_dir));
921 debugfs_remove_recursive(debug_dir);
922 goto end;
923 }
924
925 file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
Badhri Jagan Sridharan424861b2016-08-09 12:47:37 -0700926 &verity_enabled);
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700927
928 if (IS_ERR_OR_NULL(file)) {
929 DMERR("Cannot create android_verity debugfs directory: %ld",
930 PTR_ERR(debug_dir));
931 debugfs_remove_recursive(debug_dir);
932 }
933
934end:
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800935 return r;
936}
937
938static void __exit dm_android_verity_exit(void)
939{
Badhri Jagan Sridharand0706bc2016-03-21 10:55:23 -0700940 if (!IS_ERR_OR_NULL(debug_dir))
941 debugfs_remove_recursive(debug_dir);
942
Badhri Jagan Sridharan8bb45a52015-12-14 20:09:39 -0800943 dm_unregister_target(&android_verity_target);
944}
945
946module_init(dm_android_verity_init);
947module_exit(dm_android_verity_exit);