blob: d7096350ab0701dac7f1f0effbaf3a68ee17ba95 [file] [log] [blame]
Monika Singhb15747d2017-09-25 14:01:13 +05301/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "avb_slot_verify.h"
26#include "avb_chain_partition_descriptor.h"
27#include "avb_footer.h"
28#include "avb_hash_descriptor.h"
29#include "avb_kernel_cmdline_descriptor.h"
30#include "avb_sha.h"
31#include "avb_util.h"
32#include "avb_vbmeta_image.h"
33#include "avb_version.h"
34
35/* Maximum allow length (in bytes) of a partition name, including
36 * ab_suffix.
37 */
38#define PART_NAME_MAX_SIZE 32
39
40/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
41#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
42
43/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
44#define MAX_NUMBER_OF_VBMETA_IMAGES 32
45
46/* Maximum size of a vbmeta image - 64 KiB. */
47#define VBMETA_MAX_SIZE (64 * 1024)
48
49/* Helper function to see if we should continue with verification in
50 * allow_verification_error=true mode if something goes wrong. See the
51 * comments for the avb_slot_verify() function for more information.
52 */
53static inline bool result_should_continue(AvbSlotVerifyResult result) {
54 switch (result) {
55 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
56 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
57 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
58 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
59 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
60 return false;
61
62 case AVB_SLOT_VERIFY_RESULT_OK:
63 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
64 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
65 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
66 return true;
67 }
68
69 return false;
70}
71
72static AvbSlotVerifyResult load_and_verify_hash_partition(
73 AvbOps* ops,
74 const char* const* requested_partitions,
75 const char* ab_suffix,
76 bool allow_verification_error,
77 const AvbDescriptor* descriptor,
78 AvbSlotVerifyData* slot_data) {
79 AvbHashDescriptor hash_desc;
80 const uint8_t* desc_partition_name = NULL;
81 const uint8_t* desc_salt;
82 const uint8_t* desc_digest;
83 char part_name[PART_NAME_MAX_SIZE];
84 AvbSlotVerifyResult ret;
85 AvbIOResult io_ret;
86 uint8_t* image_buf = NULL;
87 size_t part_num_read;
88 uint8_t* digest = NULL;
89 size_t digest_len;
90 const char* found = NULL;
91 uint64_t image_size;
92
93 if (!avb_hash_descriptor_validate_and_byteswap(
94 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
95 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
96 goto out;
97 }
98 desc_partition_name =
99 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
100 desc_salt = desc_partition_name + hash_desc.partition_name_len;
101 desc_digest = desc_salt + hash_desc.salt_len;
102
103 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
104 avb_error("Partition name is not valid UTF-8.\n");
105 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
106 goto out;
107 }
108
109 /* Don't bother loading or validating unless the partition was
110 * requested in the first place.
111 */
112 found = avb_strv_find_str(requested_partitions,
113 (const char*)desc_partition_name,
114 hash_desc.partition_name_len);
115 if (found == NULL) {
116 ret = AVB_SLOT_VERIFY_RESULT_OK;
117 goto out;
118 }
119
120 if (!avb_str_concat(part_name,
121 sizeof part_name,
122 (const char*)desc_partition_name,
123 hash_desc.partition_name_len,
124 ab_suffix,
125 avb_strlen(ab_suffix))) {
126 avb_error("Partition name and suffix does not fit.\n");
127 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
128 goto out;
129 }
130
131 /* If we're allowing verification errors then hash_desc.image_size
132 * may no longer match what's in the partition... so in this case
133 * just load the entire partition.
134 *
135 * For example, this can happen if a developer does 'fastboot flash
136 * boot /path/to/new/and/bigger/boot.img'. We want this to work
137 * since it's such a common workflow.
138 */
139 image_size = hash_desc.image_size;
140 if (allow_verification_error) {
141 if (ops->get_size_of_partition == NULL) {
142 avb_errorv(part_name,
143 ": The get_size_of_partition() operation is "
144 "not implemented so we may not load the entire partition. "
145 "Please implement.",
146 NULL);
147 } else {
148 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
149 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
150 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
151 goto out;
152 } else if (io_ret != AVB_IO_RESULT_OK) {
153 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
154 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
155 goto out;
156 }
157 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
158 }
159 }
160
161 image_buf = (uint8_t *)target_get_scratch_address()+0x02000000;
162 if (image_buf == NULL) {
163 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
164 goto out;
165 }
166
167 if (!strncmp(part_name, "boot", strlen("boot"))) {
168 image_size = hash_desc.image_size;
169 io_ret = ops->read_from_partition(
170 ops, part_name, 0 /* offset */, image_size, &image_buf, &part_num_read);
171 } else {
172 io_ret = ops->read_from_partition(
173 ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
174 }
175 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
176 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
177 goto out;
178 } else if (io_ret != AVB_IO_RESULT_OK) {
179 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
180 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
181 goto out;
182 }
183 if (part_num_read != image_size) {
184 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
185 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
186 goto out;
187 }
188
189 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
190 uint32_t complete_len = hash_desc.salt_len + hash_desc.image_size;
191 uint8_t *complete_buf = (uint8_t *)target_get_scratch_address()+0x08000000;
192 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +0530193 if(digest == NULL)
194 {
195 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
196 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
197 goto out;
198 }
Monika Singhb15747d2017-09-25 14:01:13 +0530199 avb_memcpy(complete_buf, desc_salt, hash_desc.salt_len);
200 avb_memcpy(complete_buf + hash_desc.salt_len, image_buf, hash_desc.image_size);
201 hash_find(complete_buf, complete_len, digest, CRYPTO_AUTH_ALG_SHA256);
202 digest_len = AVB_SHA256_DIGEST_SIZE;
203 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
204 AvbSHA512Ctx sha512_ctx;
205 uint8_t *dig;
206 digest = avb_malloc(AVB_SHA512_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +0530207 if(digest == NULL)
208 {
209 avb_errorv(part_name, ": Failed to allocate memory\n", NULL);
210 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
211 goto out;
212 }
Monika Singhb15747d2017-09-25 14:01:13 +0530213 avb_sha512_init(&sha512_ctx);
214 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
215 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
216 dig = avb_sha512_final(&sha512_ctx);
217 digest_len = AVB_SHA512_DIGEST_SIZE;
218 avb_memcpy(digest, dig, AVB_SHA512_DIGEST_SIZE);
219 } else {
220 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
221 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
222 goto out;
223 }
224
225 if (digest_len != hash_desc.digest_len) {
226 avb_errorv(
227 part_name, ": Digest in descriptor not of expected size.\n", NULL);
228 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
229 goto out;
230 }
231
232 if (avb_safe_memcmp(digest, desc_digest, digest_len) != 0) {
233 avb_errorv(part_name,
234 ": Hash of data does not match digest in descriptor.\n",
235 NULL);
236 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
237 goto out;
238 }
239
240 ret = AVB_SLOT_VERIFY_RESULT_OK;
241
242out:
243 if (digest)
244 avb_free(digest);
245 /* If it worked and something was loaded, copy to slot_data. */
246 if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
247 image_buf != NULL) {
248 AvbPartitionData* loaded_partition;
249 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
250 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
251 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
252 goto fail;
253 }
254 loaded_partition =
255 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
256 loaded_partition->partition_name = avb_strdup(found);
257 loaded_partition->data_size = image_size;
258 loaded_partition->data = image_buf;
259 image_buf = NULL;
260 }
261
262fail:
263 //remove avb_free() as memory allocated from scratch region
264 return ret;
265}
266
267static AvbSlotVerifyResult load_requested_partitions(
268 AvbOps* ops,
269 const char* const* requested_partitions,
270 const char* ab_suffix,
271 AvbSlotVerifyData* slot_data) {
272 AvbSlotVerifyResult ret;
273 uint8_t* image_buf = NULL;
274 size_t n;
275
276 if (ops->get_size_of_partition == NULL) {
277 avb_error("get_size_of_partition() not implemented.\n");
278 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
279 goto out;
280 }
281
282 for (n = 0; requested_partitions[n] != NULL; n++) {
283 char part_name[PART_NAME_MAX_SIZE];
284 AvbIOResult io_ret;
285 uint64_t image_size;
286 size_t part_num_read;
287 AvbPartitionData* loaded_partition;
288
289 if (!avb_str_concat(part_name,
290 sizeof part_name,
291 requested_partitions[n],
292 avb_strlen(requested_partitions[n]),
293 ab_suffix,
294 avb_strlen(ab_suffix))) {
295 avb_error("Partition name and suffix does not fit.\n");
296 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
297 goto out;
298 }
299
300 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
301 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
302 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
303 goto out;
304 } else if (io_ret != AVB_IO_RESULT_OK) {
305 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
306 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
307 goto out;
308 }
309 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
310
311 image_buf = avb_malloc(image_size);
312 if (image_buf == NULL) {
313 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
314 goto out;
315 }
316
317 io_ret = ops->read_from_partition(
318 ops, part_name, 0 /* offset */, image_size, image_buf, &part_num_read);
319 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
320 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
321 goto out;
322 } else if (io_ret != AVB_IO_RESULT_OK) {
323 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
324 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
325 goto out;
326 }
327 if (part_num_read != image_size) {
328 avb_errorv(part_name, ": Read fewer than requested bytes.\n", NULL);
329 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
330 goto out;
331 }
332
333 /* Move to slot_data. */
334 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
335 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
336 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
337 goto out;
338 }
339 loaded_partition =
340 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
341 loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
342 if (loaded_partition->partition_name == NULL) {
343 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
344 goto out;
345 }
346 loaded_partition->data_size = image_size;
347 loaded_partition->data = image_buf;
348 image_buf = NULL;
349 }
350
351 ret = AVB_SLOT_VERIFY_RESULT_OK;
352
353out:
354 if (image_buf != NULL) {
355 avb_free(image_buf);
356 }
357 return ret;
358}
359
360static AvbSlotVerifyResult load_and_verify_vbmeta(
361 AvbOps* ops,
362 const char* const* requested_partitions,
363 const char* ab_suffix,
364 bool allow_verification_error,
365 AvbVBMetaImageFlags toplevel_vbmeta_flags,
366 int rollback_index_location,
367 const char* partition_name,
368 size_t partition_name_len,
369 const uint8_t* expected_public_key,
370 size_t expected_public_key_length,
371 AvbSlotVerifyData* slot_data,
372 AvbAlgorithmType* out_algorithm_type) {
373 char full_partition_name[PART_NAME_MAX_SIZE];
374 AvbSlotVerifyResult ret;
375 AvbIOResult io_ret;
376 size_t vbmeta_offset;
377 size_t vbmeta_size;
378 uint8_t* vbmeta_buf = NULL;
379 size_t vbmeta_num_read;
380 AvbVBMetaVerifyResult vbmeta_ret;
381 const uint8_t* pk_data;
382 size_t pk_len;
383 AvbVBMetaImageHeader vbmeta_header;
384 uint64_t stored_rollback_index;
385 const AvbDescriptor** descriptors = NULL;
386 size_t num_descriptors;
387 size_t n;
388 bool is_main_vbmeta;
389 bool is_vbmeta_partition;
390 AvbVBMetaData* vbmeta_image_data = NULL;
391
392 ret = AVB_SLOT_VERIFY_RESULT_OK;
393
394 avb_assert(slot_data != NULL);
395
396 /* Since we allow top-level vbmeta in 'boot', use
397 * rollback_index_location to determine whether we're the main
398 * vbmeta struct.
399 */
400 is_main_vbmeta = (rollback_index_location == 0);
401 is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
402
403 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
404 avb_error("Partition name is not valid UTF-8.\n");
405 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
406 goto out;
407 }
408
409 /* Construct full partition name. */
410 if (!avb_str_concat(full_partition_name,
411 sizeof full_partition_name,
412 partition_name,
413 partition_name_len,
414 ab_suffix,
415 avb_strlen(ab_suffix))) {
416 avb_error("Partition name and suffix does not fit.\n");
417 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
418 goto out;
419 }
420
421 avb_debugv("Loading vbmeta struct from partition '",
422 full_partition_name,
423 "'.\n",
424 NULL);
425
426 /* If we're loading from the main vbmeta partition, the vbmeta
427 * struct is in the beginning. Otherwise we have to locate it via a
428 * footer.
429 */
430 if (is_vbmeta_partition) {
431 vbmeta_offset = 0;
432 vbmeta_size = VBMETA_MAX_SIZE;
433 } else {
434 uint8_t footer_buf[AVB_FOOTER_SIZE];
435 size_t footer_num_read;
436 AvbFooter footer;
437
438 io_ret = ops->read_from_partition(ops,
439 full_partition_name,
440 -AVB_FOOTER_SIZE,
441 AVB_FOOTER_SIZE,
442 footer_buf,
443 &footer_num_read);
444 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
445 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
446 goto out;
447 } else if (io_ret != AVB_IO_RESULT_OK) {
448 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
449 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
450 goto out;
451 }
452 avb_assert(footer_num_read == AVB_FOOTER_SIZE);
453
454 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
455 &footer)) {
456 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
457 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
458 goto out;
459 }
460
461 /* Basic footer sanity check since the data is untrusted. */
462 if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
463 avb_errorv(
464 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
465 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
466 goto out;
467 }
468
469 vbmeta_offset = footer.vbmeta_offset;
470 vbmeta_size = footer.vbmeta_size;
471 }
472
473 vbmeta_buf = (uint8_t *)target_get_scratch_address() + 0x06000000;
474 if (vbmeta_buf == NULL) {
475 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
476 goto out;
477 }
478
479 io_ret = ops->read_from_partition(ops,
480 full_partition_name,
481 vbmeta_offset,
482 vbmeta_size,
483 vbmeta_buf,
484 &vbmeta_num_read);
485 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
486 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
487 goto out;
488 } else if (io_ret != AVB_IO_RESULT_OK) {
489 /* If we're looking for 'vbmeta' but there is no such partition,
490 * go try to get it from the boot partition instead.
491 */
492 if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
493 is_vbmeta_partition) {
494 avb_debugv(full_partition_name,
495 ": No such partition. Trying 'boot' instead.\n",
496 NULL);
497 ret = load_and_verify_vbmeta(ops,
498 requested_partitions,
499 ab_suffix,
500 allow_verification_error,
501 0 /* toplevel_vbmeta_flags */,
502 0 /* rollback_index_location */,
503 "boot",
504 avb_strlen("boot"),
505 NULL /* expected_public_key */,
506 0 /* expected_public_key_length */,
507 slot_data,
508 out_algorithm_type);
509 goto out;
510 } else {
511 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
512 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
513 goto out;
514 }
515 }
516 avb_assert(vbmeta_num_read <= vbmeta_size);
517
518 /* Check if the image is properly signed and get the public key used
519 * to sign the image.
520 */
521 vbmeta_ret =
522 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
523 switch (vbmeta_ret) {
524 case AVB_VBMETA_VERIFY_RESULT_OK:
525 avb_assert(pk_data != NULL && pk_len > 0);
526 break;
527
528 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
529 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
530 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
531 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
532 avb_errorv(full_partition_name,
533 ": Error verifying vbmeta image: ",
534 avb_vbmeta_verify_result_to_string(vbmeta_ret),
535 "\n",
536 NULL);
537 if (!allow_verification_error) {
538 goto out;
539 }
540 break;
541
542 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
543 /* No way to continue this case. */
544 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
545 avb_errorv(full_partition_name,
546 ": Error verifying vbmeta image: invalid vbmeta header\n",
547 NULL);
548 goto out;
549
550 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
551 /* No way to continue this case. */
552 ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
553 avb_errorv(full_partition_name,
554 ": Error verifying vbmeta image: unsupported AVB version\n",
555 NULL);
556 goto out;
557 }
558
559 /* Byteswap the header. */
560 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
561 &vbmeta_header);
562
563 /* If we're the toplevel, assign flags so they'll be passed down. */
564 if (is_main_vbmeta) {
565 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
566 } else {
567 if (vbmeta_header.flags != 0) {
568 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
569 avb_errorv(full_partition_name,
570 ": chained vbmeta image has non-zero flags\n",
571 NULL);
572 goto out;
573 }
574 }
575
576 /* Check if key used to make signature matches what is expected. */
577 if (pk_data != NULL) {
578 if (expected_public_key != NULL) {
579 avb_assert(!is_main_vbmeta);
580 if (expected_public_key_length != pk_len ||
581 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
582 avb_errorv(full_partition_name,
583 ": Public key used to sign data does not match key in chain "
584 "partition descriptor.\n",
585 NULL);
586 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
587 if (!allow_verification_error) {
588 goto out;
589 }
590 }
591 } else {
592 bool key_is_trusted = false;
593 const uint8_t* pk_metadata = NULL;
594 size_t pk_metadata_len = 0;
595
596 if (vbmeta_header.public_key_metadata_size > 0) {
597 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
598 vbmeta_header.authentication_data_block_size +
599 vbmeta_header.public_key_metadata_offset;
600 pk_metadata_len = vbmeta_header.public_key_metadata_size;
601 }
602
603 avb_assert(is_main_vbmeta);
604 io_ret = ops->validate_vbmeta_public_key(
605 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
606 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
607 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
608 goto out;
609 } else if (io_ret != AVB_IO_RESULT_OK) {
610 avb_errorv(full_partition_name,
611 ": Error while checking public key used to sign data.\n",
612 NULL);
613 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
614 goto out;
615 }
616 if (!key_is_trusted) {
617 avb_errorv(full_partition_name,
618 ": Public key used to sign data rejected.\n",
619 NULL);
620 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
621 if (!allow_verification_error) {
622 goto out;
623 }
624 }
625 }
626 }
627
628 /* Check rollback index. */
629 io_ret = ops->read_rollback_index(
630 ops, rollback_index_location, &stored_rollback_index);
631 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
632 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
633 goto out;
634 } else if (io_ret != AVB_IO_RESULT_OK) {
635 avb_errorv(full_partition_name,
636 ": Error getting rollback index for location.\n",
637 NULL);
638 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
639 goto out;
640 }
641 if (vbmeta_header.rollback_index < stored_rollback_index) {
642 avb_errorv(
643 full_partition_name,
644 ": Image rollback index is less than the stored rollback index.\n",
645 NULL);
646 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
647 if (!allow_verification_error) {
648 goto out;
649 }
650 }
651
Monika Singh2c9d2b82018-05-01 12:24:59 +0530652 if (stored_rollback_index < vbmeta_header.rollback_index) {
653 io_ret = ops->write_rollback_index(
654 ops, rollback_index_location, vbmeta_header.rollback_index);
655 if (io_ret != AVB_IO_RESULT_OK) {
656 avb_errorv(full_partition_name,
657 ": Error storing rollback index for location.\n",
658 NULL);
659 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
660 goto out;
661 }
662 }
663
Monika Singhb15747d2017-09-25 14:01:13 +0530664 /* Copy vbmeta to vbmeta_images before recursing. */
665 if (is_main_vbmeta) {
666 avb_assert(slot_data->num_vbmeta_images == 0);
667 } else {
668 avb_assert(slot_data->num_vbmeta_images > 0);
669 }
670 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
671 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
672 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
673 goto out;
674 }
675 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
676 vbmeta_image_data->partition_name = avb_strdup(partition_name);
677 vbmeta_image_data->vbmeta_data = vbmeta_buf;
678 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
679 * and this includes data past the end of the image. Pass the
680 * actual size of the vbmeta image. Also, no need to use
681 * avb_safe_add() since the header has already been verified.
682 */
683 vbmeta_image_data->vbmeta_size =
684 sizeof(AvbVBMetaImageHeader) +
685 vbmeta_header.authentication_data_block_size +
686 vbmeta_header.auxiliary_data_block_size;
687 vbmeta_image_data->verify_result = vbmeta_ret;
688
689 /* If verification has been disabled by setting a bit in the image,
690 * we're done... except that we need to load the entirety of the
691 * requested partitions.
692 */
693 if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
694 AvbSlotVerifyResult sub_ret;
695 avb_debugv(
696 full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
697 /* If load_requested_partitions() fail it is always a fatal
698 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
699 * than recoverable (e.g. one where result_should_continue()
700 * returns true) and we want to convey that error.
701 */
702 sub_ret = load_requested_partitions(
703 ops, requested_partitions, ab_suffix, slot_data);
704 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
705 ret = sub_ret;
706 }
707 goto out;
708 }
709
710 /* Now go through all descriptors and take the appropriate action:
711 *
712 * - hash descriptor: Load data from partition, calculate hash, and
713 * checks that it matches what's in the hash descriptor.
714 *
715 * - hashtree descriptor: Do nothing since verification happens
716 * on-the-fly from within the OS.
717 *
718 * - chained partition descriptor: Load the footer, load the vbmeta
719 * image, verify vbmeta image (includes rollback checks, hash
720 * checks, bail on chained partitions).
721 */
722 descriptors =
723 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
724 for (n = 0; n < num_descriptors; n++) {
725 AvbDescriptor desc;
726
727 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
728 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
729 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
730 goto out;
731 }
732
733 switch (desc.tag) {
734 case AVB_DESCRIPTOR_TAG_HASH: {
735 AvbSlotVerifyResult sub_ret;
736 sub_ret = load_and_verify_hash_partition(ops,
737 requested_partitions,
738 ab_suffix,
739 allow_verification_error,
740 descriptors[n],
741 slot_data);
742 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
743 ret = sub_ret;
744 if (!allow_verification_error || !result_should_continue(ret)) {
745 goto out;
746 }
747 }
748 } break;
749
750 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
751 AvbSlotVerifyResult sub_ret;
752 AvbChainPartitionDescriptor chain_desc;
753 const uint8_t* chain_partition_name;
754 const uint8_t* chain_public_key;
755
756 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
757 if (!is_main_vbmeta) {
758 avb_errorv(full_partition_name,
759 ": Encountered chain descriptor not in main image.\n",
760 NULL);
761 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
762 goto out;
763 }
764
765 if (!avb_chain_partition_descriptor_validate_and_byteswap(
766 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
767 avb_errorv(full_partition_name,
768 ": Chain partition descriptor is invalid.\n",
769 NULL);
770 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
771 goto out;
772 }
773
774 if (chain_desc.rollback_index_location == 0) {
775 avb_errorv(full_partition_name,
776 ": Chain partition has invalid "
777 "rollback_index_location field.\n",
778 NULL);
779 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
780 goto out;
781 }
782
783 chain_partition_name = ((const uint8_t*)descriptors[n]) +
784 sizeof(AvbChainPartitionDescriptor);
785 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
786
787 sub_ret = load_and_verify_vbmeta(ops,
788 requested_partitions,
789 ab_suffix,
790 allow_verification_error,
791 toplevel_vbmeta_flags,
792 chain_desc.rollback_index_location,
793 (const char*)chain_partition_name,
794 chain_desc.partition_name_len,
795 chain_public_key,
796 chain_desc.public_key_len,
797 slot_data,
798 NULL /* out_algorithm_type */);
799 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
800 ret = sub_ret;
801 if (!result_should_continue(ret)) {
802 goto out;
803 }
804 }
805 } break;
806
807 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
808 const uint8_t* kernel_cmdline;
809 AvbKernelCmdlineDescriptor kernel_cmdline_desc;
810 bool apply_cmdline;
811
812 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
813 (AvbKernelCmdlineDescriptor*)descriptors[n],
814 &kernel_cmdline_desc)) {
815 avb_errorv(full_partition_name,
816 ": Kernel cmdline descriptor is invalid.\n",
817 NULL);
818 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
819 goto out;
820 }
821
822 kernel_cmdline = ((const uint8_t*)descriptors[n]) +
823 sizeof(AvbKernelCmdlineDescriptor);
824
825 if (!avb_validate_utf8(kernel_cmdline,
826 kernel_cmdline_desc.kernel_cmdline_length)) {
827 avb_errorv(full_partition_name,
828 ": Kernel cmdline is not valid UTF-8.\n",
829 NULL);
830 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
831 goto out;
832 }
833
834 /* Compare the flags for top-level VBMeta struct with flags in
835 * the command-line descriptor so command-line snippets only
836 * intended for a certain mode (dm-verity enabled/disabled)
837 * are skipped if applicable.
838 */
839 apply_cmdline = true;
840 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
841 if (kernel_cmdline_desc.flags &
842 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
843 apply_cmdline = false;
844 }
845 } else {
846 if (kernel_cmdline_desc.flags &
847 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
848 apply_cmdline = false;
849 }
850 }
851
852 if (apply_cmdline) {
853 if (slot_data->cmdline == NULL) {
854 slot_data->cmdline =
855 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
856 if (slot_data->cmdline == NULL) {
857 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
858 goto out;
859 }
860 avb_memcpy(slot_data->cmdline,
861 kernel_cmdline,
862 kernel_cmdline_desc.kernel_cmdline_length);
863 } else {
864 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
865 size_t orig_size = avb_strlen(slot_data->cmdline);
866 size_t new_size =
867 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
868 char* new_cmdline = avb_calloc(new_size);
869 if (new_cmdline == NULL) {
870 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
871 goto out;
872 }
873 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
874 new_cmdline[orig_size] = ' ';
875 avb_memcpy(new_cmdline + orig_size + 1,
876 kernel_cmdline,
877 kernel_cmdline_desc.kernel_cmdline_length);
878 avb_free(slot_data->cmdline);
879 slot_data->cmdline = new_cmdline;
880 }
881 }
882 } break;
883
884 /* Explicit fall-through */
885 case AVB_DESCRIPTOR_TAG_PROPERTY:
886 case AVB_DESCRIPTOR_TAG_HASHTREE:
887 /* Do nothing. */
888 break;
889 }
890 }
891
892 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
893 avb_errorv(
894 full_partition_name, ": Invalid rollback_index_location.\n", NULL);
895 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
896 goto out;
897 }
898
899 slot_data->rollback_indexes[rollback_index_location] =
900 vbmeta_header.rollback_index;
901
902 if (out_algorithm_type != NULL) {
903 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
904 }
905
906out:
907 /* If |vbmeta_image_data| isn't NULL it means that it adopted
908 * |vbmeta_buf| so in that case don't free it here.
909 */
910
911 /* remove avb_free() as memory allocated from scratch region */
912
913 if (descriptors != NULL) {
914 avb_free(descriptors);
915 }
916 return ret;
917}
918
919#define NUM_GUIDS 3
920
921/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
922 * values. Returns NULL on OOM, otherwise the cmdline with values
923 * replaced.
924 */
925static char* sub_cmdline(AvbOps* ops,
926 const char* cmdline,
927 const char* ab_suffix,
928 bool using_boot_for_vbmeta) {
929 const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
930 const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
931 "$(ANDROID_BOOT_PARTUUID)",
932 "$(ANDROID_VBMETA_PARTUUID)"};
933 char* ret = NULL;
934 AvbIOResult io_ret;
935
936 /* Special-case for when the top-level vbmeta struct is in the boot
937 * partition.
938 */
939 if (using_boot_for_vbmeta) {
940 part_name_str[2] = "boot";
941 }
942
943 /* Replace unique partition GUIDs */
944 for (size_t n = 0; n < NUM_GUIDS; n++) {
945 char part_name[PART_NAME_MAX_SIZE];
946 char guid_buf[37];
947
948 if (!avb_str_concat(part_name,
949 sizeof part_name,
950 part_name_str[n],
951 avb_strlen(part_name_str[n]),
952 ab_suffix,
953 avb_strlen(ab_suffix))) {
954 avb_error("Partition name and suffix does not fit.\n");
955 goto fail;
956 }
957
958 io_ret = ops->get_unique_guid_for_partition(
959 ops, part_name, guid_buf, sizeof guid_buf);
960 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
961 return NULL;
962 } else if (io_ret != AVB_IO_RESULT_OK) {
963 avb_error("Error getting unique GUID for partition.\n");
964 goto fail;
965 }
966
967 if (ret == NULL) {
968 ret = avb_replace(cmdline, replace_str[n], guid_buf);
969 } else {
970 char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
971 avb_free(ret);
972 ret = new_ret;
973 }
974 if (ret == NULL) {
975 goto fail;
976 }
977 }
978
979 return ret;
980
981fail:
982 if (ret != NULL) {
983 avb_free(ret);
984 }
985 return NULL;
986}
987
988static int cmdline_append_option(AvbSlotVerifyData* slot_data,
989 const char* key,
990 const char* value) {
991 size_t offset, key_len, value_len;
992 char* new_cmdline;
993
994 key_len = avb_strlen(key);
995 value_len = avb_strlen(value);
996
997 offset = 0;
998 if (slot_data->cmdline != NULL) {
999 offset = avb_strlen(slot_data->cmdline);
1000 if (offset > 0) {
1001 offset += 1;
1002 }
1003 }
1004
1005 new_cmdline = avb_calloc(offset + key_len + value_len + 2);
1006 if (new_cmdline == NULL) {
1007 return 0;
1008 }
1009 if (offset > 0) {
1010 avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
1011 new_cmdline[offset - 1] = ' ';
1012 }
1013 avb_memcpy(new_cmdline + offset, key, key_len);
1014 new_cmdline[offset + key_len] = '=';
1015 avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
1016 if (slot_data->cmdline != NULL) {
1017 avb_free(slot_data->cmdline);
1018 }
1019 slot_data->cmdline = new_cmdline;
1020
1021 return 1;
1022}
1023
1024#define AVB_MAX_DIGITS_UINT64 32
1025
1026/* Writes |value| to |digits| in base 10 followed by a NUL byte.
1027 * Returns number of characters written excluding the NUL byte.
1028 */
1029static size_t uint64_to_base10(uint64_t value,
1030 char digits[AVB_MAX_DIGITS_UINT64]) {
1031 char rev_digits[AVB_MAX_DIGITS_UINT64];
1032 size_t n, num_digits;
1033
1034 for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
1035 rev_digits[num_digits++] = (value % 10) + '0';
1036 value /= 10;
1037 if (value == 0) {
1038 break;
1039 }
1040 }
1041
1042 for (n = 0; n < num_digits; n++) {
1043 digits[n] = rev_digits[num_digits - 1 - n];
1044 }
1045 digits[n] = '\0';
1046 return n;
1047}
1048
1049static int cmdline_append_version(AvbSlotVerifyData* slot_data,
1050 const char* key,
1051 uint64_t major_version,
1052 uint64_t minor_version) {
1053 char major_digits[AVB_MAX_DIGITS_UINT64];
1054 char minor_digits[AVB_MAX_DIGITS_UINT64];
1055 char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
1056 size_t num_major_digits, num_minor_digits;
1057
1058 num_major_digits = uint64_to_base10(major_version, major_digits);
1059 num_minor_digits = uint64_to_base10(minor_version, minor_digits);
1060 avb_memcpy(combined, major_digits, num_major_digits);
1061 combined[num_major_digits] = '.';
1062 avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
1063 combined[num_major_digits + 1 + num_minor_digits] = '\0';
1064
1065 return cmdline_append_option(slot_data, key, combined);
1066}
1067
1068static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
1069 const char* key,
1070 uint64_t value) {
1071 char digits[AVB_MAX_DIGITS_UINT64];
1072 uint64_to_base10(value, digits);
1073 return cmdline_append_option(slot_data, key, digits);
1074}
1075
1076static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
1077 const char* key,
1078 const uint8_t* data,
1079 size_t data_len) {
1080 char hex_digits[17] = "0123456789abcdef";
1081 char* hex_data;
1082 int ret;
1083 size_t n;
1084
1085 hex_data = avb_malloc(data_len * 2 + 1);
1086 if (hex_data == NULL) {
1087 return 0;
1088 }
1089
1090 for (n = 0; n < data_len; n++) {
1091 hex_data[n * 2] = hex_digits[data[n] >> 4];
1092 hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
1093 }
1094 hex_data[n * 2] = '\0';
1095
1096 ret = cmdline_append_option(slot_data, key, hex_data);
1097 avb_free(hex_data);
1098 return ret;
1099}
1100
1101static AvbSlotVerifyResult append_options(
1102 AvbOps* ops,
1103 AvbSlotVerifyData* slot_data,
1104 AvbVBMetaImageHeader* toplevel_vbmeta,
1105 AvbAlgorithmType algorithm_type,
1106 AvbHashtreeErrorMode hashtree_error_mode) {
1107 AvbSlotVerifyResult ret;
1108 const char* verity_mode = NULL;
1109 bool is_device_unlocked;
1110 AvbIOResult io_ret;
1111
1112 /* Add androidboot.vbmeta.device option. */
1113 if (!cmdline_append_option(slot_data,
1114 "androidboot.vbmeta.device",
1115 "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
1116 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1117 goto out;
1118 }
1119
1120 /* Add androidboot.vbmeta.avb_version option. */
1121 if (!cmdline_append_version(slot_data,
1122 "androidboot.vbmeta.avb_version",
1123 AVB_VERSION_MAJOR,
1124 AVB_VERSION_MINOR)) {
1125 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1126 goto out;
1127 }
1128
1129 /* Set androidboot.avb.device_state to "locked" or "unlocked". */
1130 io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
1131 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1132 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1133 goto out;
1134 } else if (io_ret != AVB_IO_RESULT_OK) {
1135 avb_error("Error getting device state.\n");
1136 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1137 goto out;
1138 }
1139 if (!cmdline_append_option(slot_data,
1140 "androidboot.vbmeta.device_state",
1141 is_device_unlocked ? "unlocked" : "locked")) {
1142 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1143 goto out;
1144 }
1145
1146 /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
1147 * function as is used to sign vbmeta.
1148 */
1149 switch (algorithm_type) {
1150 /* Explicit fallthrough. */
1151 case AVB_ALGORITHM_TYPE_NONE:
1152 case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
1153 case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
1154 case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
1155 size_t n, prev_sz = 0, total_size = 0;
1156 uint8_t* digest = NULL;
1157 uint8_t* tbuf = NULL;
1158
1159 digest = avb_malloc(AVB_SHA256_DIGEST_SIZE);
Monika Singh0f7bfc82018-04-16 23:14:29 +05301160 if(digest == NULL)
1161 {
1162 avb_error("Failed to allocate memory\n");
1163 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1164 goto out;
1165 }
Monika Singhb15747d2017-09-25 14:01:13 +05301166 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1167 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1168 }
1169 tbuf = avb_malloc(total_size);
1170
1171 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1172 avb_memcpy(tbuf + prev_sz, slot_data->vbmeta_images[n].vbmeta_data,
1173 slot_data->vbmeta_images[n].vbmeta_size);
1174 prev_sz = slot_data->vbmeta_images[n].vbmeta_size;
1175 }
1176 hash_find((unsigned char *)tbuf, total_size, digest, CRYPTO_AUTH_ALG_SHA256);
1177 avb_free(tbuf);
1178
1179 if (!cmdline_append_option(
1180 slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
1181 !cmdline_append_uint64_base10(
1182 slot_data, "androidboot.vbmeta.size", total_size) ||
1183 !cmdline_append_hex(slot_data,
1184 "androidboot.vbmeta.digest",
1185 digest,
1186 AVB_SHA256_DIGEST_SIZE)) {
1187 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1188 if (digest)
1189 avb_free(digest);
1190 goto out;
1191 }
1192 if (digest)
1193 avb_free(digest);
1194 } break;
1195 /* Explicit fallthrough. */
1196 case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
1197 case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
1198 case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
1199 AvbSHA512Ctx ctx;
1200 size_t n, total_size = 0;
1201 avb_sha512_init(&ctx);
1202 for (n = 0; n < slot_data->num_vbmeta_images; n++) {
1203 avb_sha512_update(&ctx,
1204 slot_data->vbmeta_images[n].vbmeta_data,
1205 slot_data->vbmeta_images[n].vbmeta_size);
1206 total_size += slot_data->vbmeta_images[n].vbmeta_size;
1207 }
1208 if (!cmdline_append_option(
1209 slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
1210 !cmdline_append_uint64_base10(
1211 slot_data, "androidboot.vbmeta.size", total_size) ||
1212 !cmdline_append_hex(slot_data,
1213 "androidboot.vbmeta.digest",
1214 avb_sha512_final(&ctx),
1215 AVB_SHA512_DIGEST_SIZE)) {
1216 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1217 goto out;
1218 }
1219 } break;
1220 case _AVB_ALGORITHM_NUM_TYPES:
1221 avb_assert_not_reached();
1222 break;
1223 }
1224
1225 /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
1226 if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1227 verity_mode = "disabled";
1228 } else {
1229 const char* dm_verity_mode = NULL;
1230 char* new_ret;
1231
1232 switch (hashtree_error_mode) {
1233 case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
1234 if (!cmdline_append_option(
1235 slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
1236 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1237 goto out;
1238 }
1239 verity_mode = "enforcing";
1240 dm_verity_mode = "restart_on_corruption";
1241 break;
1242 case AVB_HASHTREE_ERROR_MODE_RESTART:
1243 verity_mode = "enforcing";
1244 dm_verity_mode = "restart_on_corruption";
1245 break;
1246 case AVB_HASHTREE_ERROR_MODE_EIO:
1247 verity_mode = "eio";
1248 /* For now there's no option to specify the EIO mode. So
1249 * just use 'ignore_zero_blocks' since that's already set
1250 * and dm-verity-target.c supports specifying this multiple
1251 * times.
1252 */
1253 dm_verity_mode = "ignore_zero_blocks";
1254 break;
1255 case AVB_HASHTREE_ERROR_MODE_LOGGING:
1256 verity_mode = "logging";
1257 dm_verity_mode = "ignore_corruption";
1258 break;
1259 }
1260 new_ret = avb_replace(
1261 slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
1262 avb_free(slot_data->cmdline);
1263 slot_data->cmdline = new_ret;
1264 if (slot_data->cmdline == NULL) {
1265 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1266 goto out;
1267 }
1268 }
1269 if (!cmdline_append_option(
1270 slot_data, "androidboot.veritymode", verity_mode)) {
1271 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1272 goto out;
1273 }
1274
1275 ret = AVB_SLOT_VERIFY_RESULT_OK;
1276
1277out:
1278
1279 return ret;
1280}
1281
1282AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1283 const char* const* requested_partitions,
1284 const char* ab_suffix,
1285 AvbSlotVerifyFlags flags,
1286 AvbHashtreeErrorMode hashtree_error_mode,
1287 AvbSlotVerifyData** out_data) {
1288 AvbSlotVerifyResult ret;
1289 AvbSlotVerifyData* slot_data = NULL;
1290 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1291 bool using_boot_for_vbmeta = false;
1292 AvbVBMetaImageHeader toplevel_vbmeta;
1293 bool allow_verification_error =
1294 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1295
1296 /* Fail early if we're missing the AvbOps needed for slot verification.
1297 *
1298 * For now, handle get_size_of_partition() not being implemented. In
1299 * a later release we may change that.
1300 */
1301 avb_assert(ops->read_is_device_unlocked != NULL);
1302 avb_assert(ops->read_from_partition != NULL);
1303 avb_assert(ops->validate_vbmeta_public_key != NULL);
1304 avb_assert(ops->read_rollback_index != NULL);
1305 avb_assert(ops->get_unique_guid_for_partition != NULL);
1306 /* avb_assert(ops->get_size_of_partition != NULL); */
1307
1308 if (out_data != NULL) {
1309 *out_data = NULL;
1310 }
1311
1312 /* Allowing dm-verity errors defeats the purpose of verified boot so
1313 * only allow this if set up to allow verification errors
1314 * (e.g. typically only UNLOCKED mode).
1315 */
1316 if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1317 !allow_verification_error) {
1318 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1319 goto fail;
1320 }
1321
1322 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1323 if (slot_data == NULL) {
1324 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1325 goto fail;
1326 }
1327 slot_data->vbmeta_images =
1328 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1329 if (slot_data->vbmeta_images == NULL) {
1330 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1331 goto fail;
1332 }
1333 slot_data->loaded_partitions =
1334 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1335 if (slot_data->loaded_partitions == NULL) {
1336 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1337 goto fail;
1338 }
1339
1340 ret = load_and_verify_vbmeta(ops,
1341 requested_partitions,
1342 ab_suffix,
1343 allow_verification_error,
1344 0 /* toplevel_vbmeta_flags */,
1345 0 /* rollback_index_location */,
1346 "vbmeta",
1347 avb_strlen("vbmeta"),
1348 NULL /* expected_public_key */,
1349 0 /* expected_public_key_length */,
1350 slot_data,
1351 &algorithm_type);
1352 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1353 goto fail;
1354 }
1355
1356 /* If things check out, mangle the kernel command-line as needed. */
1357 if (result_should_continue(ret)) {
1358 if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1359 avb_assert(
1360 avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1361 using_boot_for_vbmeta = true;
1362 }
1363
1364 /* Byteswap top-level vbmeta header since we'll need it below. */
1365 avb_vbmeta_image_header_to_host_byte_order(
1366 (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1367 &toplevel_vbmeta);
1368
1369 /* Fill in |ab_suffix| field. */
1370 slot_data->ab_suffix = avb_strdup(ab_suffix);
1371 if (slot_data->ab_suffix == NULL) {
1372 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1373 goto fail;
1374 }
1375
1376 /* If verification is disabled, we are done ... we specifically
1377 * don't want to add any androidboot.* options since verification
1378 * is disabled.
1379 */
1380 if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1381 /* Since verification is disabled we didn't process any
1382 * descriptors and thus there's no cmdline... so set root= such
1383 * that the system partition is mounted.
1384 */
1385 avb_assert(slot_data->cmdline == NULL);
1386 slot_data->cmdline =
1387 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1388 if (slot_data->cmdline == NULL) {
1389 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1390 goto fail;
1391 }
1392 } else {
1393 /* Add options - any failure in append_options() is either an
1394 * I/O or OOM error.
1395 */
1396 AvbSlotVerifyResult sub_ret = append_options(ops,
1397 slot_data,
1398 &toplevel_vbmeta,
1399 algorithm_type,
1400 hashtree_error_mode);
1401 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1402 ret = sub_ret;
1403 goto fail;
1404 }
1405 }
1406
1407 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1408 if (slot_data->cmdline != NULL) {
1409 char* new_cmdline;
1410 new_cmdline = sub_cmdline(
1411 ops, slot_data->cmdline, ab_suffix, using_boot_for_vbmeta);
1412 if (new_cmdline == NULL) {
1413 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1414 goto fail;
1415 }
1416 avb_free(slot_data->cmdline);
1417 slot_data->cmdline = new_cmdline;
1418 }
1419
1420 if (out_data != NULL) {
1421 *out_data = slot_data;
1422 } else {
1423 avb_slot_verify_data_free(slot_data);
1424 }
1425 }
1426
1427 if (!allow_verification_error) {
1428 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1429 }
1430
1431 return ret;
1432
1433fail:
1434 if (slot_data != NULL) {
1435 avb_slot_verify_data_free(slot_data);
1436 }
1437 return ret;
1438}
1439
1440void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1441 if (data->ab_suffix != NULL) {
1442 avb_free(data->ab_suffix);
1443 }
1444 if (data->cmdline != NULL) {
1445 avb_free(data->cmdline);
1446 }
1447 if (data->vbmeta_images != NULL) {
1448 size_t n;
1449 for (n = 0; n < data->num_vbmeta_images; n++) {
1450 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1451 if (vbmeta_image->partition_name != NULL) {
1452 avb_free(vbmeta_image->partition_name);
1453 }
1454 if (vbmeta_image->vbmeta_data != NULL) {
1455 vbmeta_image->vbmeta_data = NULL;
1456 }
1457 }
1458 avb_free(data->vbmeta_images);
1459 }
1460 if (data->loaded_partitions != NULL) {
1461 size_t n;
1462 for (n = 0; n < data->num_loaded_partitions; n++) {
1463 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1464 if (loaded_partition->partition_name != NULL) {
1465 avb_free(loaded_partition->partition_name);
1466 }
1467 if (loaded_partition->data != NULL) {
1468 if (data->num_loaded_partitions == 1)
1469 loaded_partition->data = NULL;
1470 }
1471 }
1472 avb_free(data->loaded_partitions);
1473 }
1474 avb_free(data);
1475}
1476
1477const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1478 const char* ret = NULL;
1479
1480 switch (result) {
1481 case AVB_SLOT_VERIFY_RESULT_OK:
1482 ret = "OK";
1483 break;
1484 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1485 ret = "ERROR_OOM";
1486 break;
1487 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1488 ret = "ERROR_IO";
1489 break;
1490 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1491 ret = "ERROR_VERIFICATION";
1492 break;
1493 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1494 ret = "ERROR_ROLLBACK_INDEX";
1495 break;
1496 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1497 ret = "ERROR_PUBLIC_KEY_REJECTED";
1498 break;
1499 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1500 ret = "ERROR_INVALID_METADATA";
1501 break;
1502 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1503 ret = "ERROR_UNSUPPORTED_VERSION";
1504 break;
1505 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1506 ret = "ERROR_INVALID_ARGUMENT";
1507 break;
1508 /* Do not add a 'default:' case here because of -Wswitch. */
1509 }
1510
1511 if (ret == NULL) {
1512 avb_error("Unknown AvbSlotVerifyResult value.\n");
1513 ret = "(unknown)";
1514 }
1515
1516 return ret;
1517}