blob: 66ac6f03bb664482f46a8179340572bee051c28f [file] [log] [blame]
Igor Opaniukd8f9d2a2018-06-03 21:56:36 +03001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include "avb_slot_verify.h"
8#include "avb_chain_partition_descriptor.h"
9#include "avb_cmdline.h"
10#include "avb_footer.h"
11#include "avb_hash_descriptor.h"
12#include "avb_hashtree_descriptor.h"
13#include "avb_kernel_cmdline_descriptor.h"
14#include "avb_sha.h"
15#include "avb_util.h"
16#include "avb_vbmeta_image.h"
17#include "avb_version.h"
18
19/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
20#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
21
22/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
23#define MAX_NUMBER_OF_VBMETA_IMAGES 32
24
25/* Maximum size of a vbmeta image - 64 KiB. */
26#define VBMETA_MAX_SIZE (64 * 1024)
27
28/* Helper function to see if we should continue with verification in
29 * allow_verification_error=true mode if something goes wrong. See the
30 * comments for the avb_slot_verify() function for more information.
31 */
32static inline bool result_should_continue(AvbSlotVerifyResult result) {
33 switch (result) {
34 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
35 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
36 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
37 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
38 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
39 return false;
40
41 case AVB_SLOT_VERIFY_RESULT_OK:
42 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
43 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
44 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
45 return true;
46 }
47
48 return false;
49}
50
51static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
52 const char* part_name,
53 uint64_t image_size,
54 uint8_t** out_image_buf,
55 bool* out_image_preloaded) {
56 size_t part_num_read;
57 AvbIOResult io_ret;
58
59 /* Make sure that we do not overwrite existing data. */
60 avb_assert(*out_image_buf == NULL);
61 avb_assert(!*out_image_preloaded);
62
63 /* We are going to implicitly cast image_size from uint64_t to size_t in the
64 * following code, so we need to make sure that the cast is safe. */
65 if (image_size != (size_t)(image_size)) {
66 avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
67 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
68 }
69
70 /* Try use a preloaded one. */
71 if (ops->get_preloaded_partition != NULL) {
72 io_ret = ops->get_preloaded_partition(
73 ops, part_name, image_size, out_image_buf, &part_num_read);
74 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
75 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
76 } else if (io_ret != AVB_IO_RESULT_OK) {
77 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
78 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
79 }
80
81 if (*out_image_buf != NULL) {
82 if (part_num_read != image_size) {
83 avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
84 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
85 }
86 *out_image_preloaded = true;
87 }
88 }
89
90 /* Allocate and copy the partition. */
91 if (!*out_image_preloaded) {
92 *out_image_buf = avb_malloc(image_size);
93 if (*out_image_buf == NULL) {
94 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
95 }
96
97 io_ret = ops->read_from_partition(ops,
98 part_name,
99 0 /* offset */,
100 image_size,
101 *out_image_buf,
102 &part_num_read);
103 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
104 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
105 } else if (io_ret != AVB_IO_RESULT_OK) {
106 avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
107 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
108 }
109 if (part_num_read != image_size) {
110 avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
111 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
112 }
113 }
114
115 return AVB_SLOT_VERIFY_RESULT_OK;
116}
117
118static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
119 const char* part_name,
120 size_t expected_digest_size,
121 uint8_t* out_digest) {
122 char* persistent_value_name = NULL;
123 AvbIOResult io_ret = AVB_IO_RESULT_OK;
124 size_t stored_digest_size = 0;
125
126 if (ops->read_persistent_value == NULL) {
127 avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
128 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
129 }
130 persistent_value_name =
131 avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
132 if (persistent_value_name == NULL) {
133 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
134 }
135 io_ret = ops->read_persistent_value(ops,
136 persistent_value_name,
137 expected_digest_size,
138 out_digest,
139 &stored_digest_size);
140 avb_free(persistent_value_name);
141 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
142 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
143 } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
144 avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
145 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
146 } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
147 io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE ||
148 expected_digest_size != stored_digest_size) {
149 avb_errorv(
150 part_name, ": Persistent digest is not of expected size.\n", NULL);
151 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
152 } else if (io_ret != AVB_IO_RESULT_OK) {
153 avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
154 return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
155 }
156 return AVB_SLOT_VERIFY_RESULT_OK;
157}
158
159static AvbSlotVerifyResult load_and_verify_hash_partition(
160 AvbOps* ops,
161 const char* const* requested_partitions,
162 const char* ab_suffix,
163 bool allow_verification_error,
164 const AvbDescriptor* descriptor,
165 AvbSlotVerifyData* slot_data) {
166 AvbHashDescriptor hash_desc;
167 const uint8_t* desc_partition_name = NULL;
168 const uint8_t* desc_salt;
169 const uint8_t* desc_digest;
170 char part_name[AVB_PART_NAME_MAX_SIZE];
171 AvbSlotVerifyResult ret;
172 AvbIOResult io_ret;
173 uint8_t* image_buf = NULL;
174 bool image_preloaded = false;
175 uint8_t* digest;
176 size_t digest_len;
177 const char* found;
178 uint64_t image_size;
179 size_t expected_digest_len = 0;
180 uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
181 const uint8_t* expected_digest = NULL;
182
183 if (!avb_hash_descriptor_validate_and_byteswap(
184 (const AvbHashDescriptor*)descriptor, &hash_desc)) {
185 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
186 goto out;
187 }
188
189 desc_partition_name =
190 ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
191 desc_salt = desc_partition_name + hash_desc.partition_name_len;
192 desc_digest = desc_salt + hash_desc.salt_len;
193
194 if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
195 avb_error("Partition name is not valid UTF-8.\n");
196 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
197 goto out;
198 }
199
200 /* Don't bother loading or validating unless the partition was
201 * requested in the first place.
202 */
203 found = avb_strv_find_str(requested_partitions,
204 (const char*)desc_partition_name,
205 hash_desc.partition_name_len);
206 if (found == NULL) {
207 ret = AVB_SLOT_VERIFY_RESULT_OK;
208 goto out;
209 }
210
211 if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
212 /* No ab_suffix, just copy the partition name as is. */
213 if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
214 avb_error("Partition name does not fit.\n");
215 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
216 goto out;
217 }
218 avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
219 part_name[hash_desc.partition_name_len] = '\0';
220 } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
221 /* No ab_suffix allowed for partitions without a digest in the descriptor
222 * because these partitions hold data unique to this device and are not
223 * updated using an A/B scheme.
224 */
225 avb_error("Cannot use A/B with a persistent digest.\n");
226 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
227 goto out;
228 } else {
229 /* Add ab_suffix to the partition name. */
230 if (!avb_str_concat(part_name,
231 sizeof part_name,
232 (const char*)desc_partition_name,
233 hash_desc.partition_name_len,
234 ab_suffix,
235 avb_strlen(ab_suffix))) {
236 avb_error("Partition name and suffix does not fit.\n");
237 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
238 goto out;
239 }
240 }
241
242 /* If we're allowing verification errors then hash_desc.image_size
243 * may no longer match what's in the partition... so in this case
244 * just load the entire partition.
245 *
246 * For example, this can happen if a developer does 'fastboot flash
247 * boot /path/to/new/and/bigger/boot.img'. We want this to work
248 * since it's such a common workflow.
249 */
250 image_size = hash_desc.image_size;
251 if (allow_verification_error) {
252 if (ops->get_size_of_partition == NULL) {
253 avb_errorv(part_name,
254 ": The get_size_of_partition() operation is "
255 "not implemented so we may not load the entire partition. "
256 "Please implement.",
257 NULL);
258 } else {
259 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
260 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
261 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
262 goto out;
263 } else if (io_ret != AVB_IO_RESULT_OK) {
264 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
265 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
266 goto out;
267 }
268 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
269 }
270 }
271
272 ret = load_full_partition(
273 ops, part_name, image_size, &image_buf, &image_preloaded);
274 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
275 goto out;
276 }
277
278 if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
279 AvbSHA256Ctx sha256_ctx;
280 avb_sha256_init(&sha256_ctx);
281 avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
282 avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
283 digest = avb_sha256_final(&sha256_ctx);
284 digest_len = AVB_SHA256_DIGEST_SIZE;
285 } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
286 AvbSHA512Ctx sha512_ctx;
287 avb_sha512_init(&sha512_ctx);
288 avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
289 avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
290 digest = avb_sha512_final(&sha512_ctx);
291 digest_len = AVB_SHA512_DIGEST_SIZE;
292 } else {
293 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
294 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
295 goto out;
296 }
297
298 if (hash_desc.digest_len == 0) {
299 // Expect a match to a persistent digest.
300 avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
301 expected_digest_len = digest_len;
302 expected_digest = expected_digest_buf;
303 avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
304 ret =
305 read_persistent_digest(ops, part_name, digest_len, expected_digest_buf);
306 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
307 goto out;
308 }
309 } else {
310 // Expect a match to the digest in the descriptor.
311 expected_digest_len = hash_desc.digest_len;
312 expected_digest = desc_digest;
313 }
314
315 if (digest_len != expected_digest_len) {
316 avb_errorv(
317 part_name, ": Digest in descriptor not of expected size.\n", NULL);
318 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
319 goto out;
320 }
321
322 if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
323 avb_errorv(part_name,
324 ": Hash of data does not match digest in descriptor.\n",
325 NULL);
326 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
327 goto out;
328 }
329
330 ret = AVB_SLOT_VERIFY_RESULT_OK;
331
332out:
333
334 /* If it worked and something was loaded, copy to slot_data. */
335 if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
336 image_buf != NULL) {
337 AvbPartitionData* loaded_partition;
338 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
339 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
340 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
341 goto fail;
342 }
343 loaded_partition =
344 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
345 loaded_partition->partition_name = avb_strdup(found);
346 loaded_partition->data_size = image_size;
347 loaded_partition->data = image_buf;
348 loaded_partition->preloaded = image_preloaded;
349 image_buf = NULL;
350 }
351
352fail:
353 if (image_buf != NULL && !image_preloaded) {
354 avb_free(image_buf);
355 }
356 return ret;
357}
358
359static AvbSlotVerifyResult load_requested_partitions(
360 AvbOps* ops,
361 const char* const* requested_partitions,
362 const char* ab_suffix,
363 AvbSlotVerifyData* slot_data) {
364 AvbSlotVerifyResult ret;
365 uint8_t* image_buf = NULL;
366 bool image_preloaded = false;
367 size_t n;
368
369 if (ops->get_size_of_partition == NULL) {
370 avb_error("get_size_of_partition() not implemented.\n");
371 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
372 goto out;
373 }
374
375 for (n = 0; requested_partitions[n] != NULL; n++) {
376 char part_name[AVB_PART_NAME_MAX_SIZE];
377 AvbIOResult io_ret;
378 uint64_t image_size;
379 AvbPartitionData* loaded_partition;
380
381 if (!avb_str_concat(part_name,
382 sizeof part_name,
383 requested_partitions[n],
384 avb_strlen(requested_partitions[n]),
385 ab_suffix,
386 avb_strlen(ab_suffix))) {
387 avb_error("Partition name and suffix does not fit.\n");
388 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
389 goto out;
390 }
391
392 io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
393 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
394 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
395 goto out;
396 } else if (io_ret != AVB_IO_RESULT_OK) {
397 avb_errorv(part_name, ": Error determining partition size.\n", NULL);
398 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
399 goto out;
400 }
401 avb_debugv(part_name, ": Loading entire partition.\n", NULL);
402
403 ret = load_full_partition(
404 ops, part_name, image_size, &image_buf, &image_preloaded);
405 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
406 goto out;
407 }
408
409 /* Move to slot_data. */
410 if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
411 avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
412 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
413 goto out;
414 }
415 loaded_partition =
416 &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
417 loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
418 if (loaded_partition->partition_name == NULL) {
419 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
420 goto out;
421 }
422 loaded_partition->data_size = image_size;
423 loaded_partition->data = image_buf; /* Transferring the owner. */
424 loaded_partition->preloaded = image_preloaded;
425 image_buf = NULL;
426 image_preloaded = false;
427 }
428
429 ret = AVB_SLOT_VERIFY_RESULT_OK;
430
431out:
432 /* Free the current buffer if any. */
433 if (image_buf != NULL && !image_preloaded) {
434 avb_free(image_buf);
435 }
436 /* Buffers that are already saved in slot_data will be handled by the caller
437 * even on failure. */
438 return ret;
439}
440
441static AvbSlotVerifyResult load_and_verify_vbmeta(
442 AvbOps* ops,
443 const char* const* requested_partitions,
444 const char* ab_suffix,
445 bool allow_verification_error,
446 AvbVBMetaImageFlags toplevel_vbmeta_flags,
447 int rollback_index_location,
448 const char* partition_name,
449 size_t partition_name_len,
450 const uint8_t* expected_public_key,
451 size_t expected_public_key_length,
452 AvbSlotVerifyData* slot_data,
453 AvbAlgorithmType* out_algorithm_type,
454 AvbCmdlineSubstList* out_additional_cmdline_subst) {
455 char full_partition_name[AVB_PART_NAME_MAX_SIZE];
456 AvbSlotVerifyResult ret;
457 AvbIOResult io_ret;
458 size_t vbmeta_offset;
459 size_t vbmeta_size;
460 uint8_t* vbmeta_buf = NULL;
461 size_t vbmeta_num_read;
462 AvbVBMetaVerifyResult vbmeta_ret;
463 const uint8_t* pk_data;
464 size_t pk_len;
465 AvbVBMetaImageHeader vbmeta_header;
466 uint64_t stored_rollback_index;
467 const AvbDescriptor** descriptors = NULL;
468 size_t num_descriptors;
469 size_t n;
470 bool is_main_vbmeta;
471 bool is_vbmeta_partition;
472 AvbVBMetaData* vbmeta_image_data = NULL;
473
474 ret = AVB_SLOT_VERIFY_RESULT_OK;
475
476 avb_assert(slot_data != NULL);
477
478 /* Since we allow top-level vbmeta in 'boot', use
479 * rollback_index_location to determine whether we're the main
480 * vbmeta struct.
481 */
482 is_main_vbmeta = (rollback_index_location == 0);
483 is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
484
485 if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
486 avb_error("Partition name is not valid UTF-8.\n");
487 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
488 goto out;
489 }
490
491 /* Construct full partition name. */
492 if (!avb_str_concat(full_partition_name,
493 sizeof full_partition_name,
494 partition_name,
495 partition_name_len,
496 ab_suffix,
497 avb_strlen(ab_suffix))) {
498 avb_error("Partition name and suffix does not fit.\n");
499 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
500 goto out;
501 }
502
503 avb_debugv("Loading vbmeta struct from partition '",
504 full_partition_name,
505 "'.\n",
506 NULL);
507
508 /* If we're loading from the main vbmeta partition, the vbmeta
509 * struct is in the beginning. Otherwise we have to locate it via a
510 * footer.
511 */
512 if (is_vbmeta_partition) {
513 vbmeta_offset = 0;
514 vbmeta_size = VBMETA_MAX_SIZE;
515 } else {
516 uint8_t footer_buf[AVB_FOOTER_SIZE];
517 size_t footer_num_read;
518 AvbFooter footer;
519
520 io_ret = ops->read_from_partition(ops,
521 full_partition_name,
522 -AVB_FOOTER_SIZE,
523 AVB_FOOTER_SIZE,
524 footer_buf,
525 &footer_num_read);
526 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
527 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
528 goto out;
529 } else if (io_ret != AVB_IO_RESULT_OK) {
530 avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
531 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
532 goto out;
533 }
534 avb_assert(footer_num_read == AVB_FOOTER_SIZE);
535
536 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
537 &footer)) {
538 avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
539 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
540 goto out;
541 }
542
543 /* Basic footer sanity check since the data is untrusted. */
544 if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
545 avb_errorv(
546 full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
547 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
548 goto out;
549 }
550
551 vbmeta_offset = footer.vbmeta_offset;
552 vbmeta_size = footer.vbmeta_size;
553 }
554
555 vbmeta_buf = avb_malloc(vbmeta_size);
556 if (vbmeta_buf == NULL) {
557 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
558 goto out;
559 }
560
561 io_ret = ops->read_from_partition(ops,
562 full_partition_name,
563 vbmeta_offset,
564 vbmeta_size,
565 vbmeta_buf,
566 &vbmeta_num_read);
567 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
568 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
569 goto out;
570 } else if (io_ret != AVB_IO_RESULT_OK) {
571 /* If we're looking for 'vbmeta' but there is no such partition,
572 * go try to get it from the boot partition instead.
573 */
574 if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
575 is_vbmeta_partition) {
576 avb_debugv(full_partition_name,
577 ": No such partition. Trying 'boot' instead.\n",
578 NULL);
579 ret = load_and_verify_vbmeta(ops,
580 requested_partitions,
581 ab_suffix,
582 allow_verification_error,
583 0 /* toplevel_vbmeta_flags */,
584 0 /* rollback_index_location */,
585 "boot",
586 avb_strlen("boot"),
587 NULL /* expected_public_key */,
588 0 /* expected_public_key_length */,
589 slot_data,
590 out_algorithm_type,
591 out_additional_cmdline_subst);
592 goto out;
593 } else {
594 avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
595 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
596 goto out;
597 }
598 }
599 avb_assert(vbmeta_num_read <= vbmeta_size);
600
601 /* Check if the image is properly signed and get the public key used
602 * to sign the image.
603 */
604 vbmeta_ret =
605 avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
606 switch (vbmeta_ret) {
607 case AVB_VBMETA_VERIFY_RESULT_OK:
608 avb_assert(pk_data != NULL && pk_len > 0);
609 break;
610
611 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
612 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
613 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
614 ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
615 avb_errorv(full_partition_name,
616 ": Error verifying vbmeta image: ",
617 avb_vbmeta_verify_result_to_string(vbmeta_ret),
618 "\n",
619 NULL);
620 if (!allow_verification_error) {
621 goto out;
622 }
623 break;
624
625 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
626 /* No way to continue this case. */
627 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
628 avb_errorv(full_partition_name,
629 ": Error verifying vbmeta image: invalid vbmeta header\n",
630 NULL);
631 goto out;
632
633 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
634 /* No way to continue this case. */
635 ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
636 avb_errorv(full_partition_name,
637 ": Error verifying vbmeta image: unsupported AVB version\n",
638 NULL);
639 goto out;
640 }
641
642 /* Byteswap the header. */
643 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
644 &vbmeta_header);
645
646 /* If we're the toplevel, assign flags so they'll be passed down. */
647 if (is_main_vbmeta) {
648 toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
649 } else {
650 if (vbmeta_header.flags != 0) {
651 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
652 avb_errorv(full_partition_name,
653 ": chained vbmeta image has non-zero flags\n",
654 NULL);
655 goto out;
656 }
657 }
658
659 /* Check if key used to make signature matches what is expected. */
660 if (pk_data != NULL) {
661 if (expected_public_key != NULL) {
662 avb_assert(!is_main_vbmeta);
663 if (expected_public_key_length != pk_len ||
664 avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
665 avb_errorv(full_partition_name,
666 ": Public key used to sign data does not match key in chain "
667 "partition descriptor.\n",
668 NULL);
669 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
670 if (!allow_verification_error) {
671 goto out;
672 }
673 }
674 } else {
675 bool key_is_trusted = false;
676 const uint8_t* pk_metadata = NULL;
677 size_t pk_metadata_len = 0;
678
679 if (vbmeta_header.public_key_metadata_size > 0) {
680 pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
681 vbmeta_header.authentication_data_block_size +
682 vbmeta_header.public_key_metadata_offset;
683 pk_metadata_len = vbmeta_header.public_key_metadata_size;
684 }
685
686 avb_assert(is_main_vbmeta);
687 io_ret = ops->validate_vbmeta_public_key(
688 ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
689 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
690 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
691 goto out;
692 } else if (io_ret != AVB_IO_RESULT_OK) {
693 avb_errorv(full_partition_name,
694 ": Error while checking public key used to sign data.\n",
695 NULL);
696 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
697 goto out;
698 }
699 if (!key_is_trusted) {
700 avb_errorv(full_partition_name,
701 ": Public key used to sign data rejected.\n",
702 NULL);
703 ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
704 if (!allow_verification_error) {
705 goto out;
706 }
707 }
708 }
709 }
710
711 /* Check rollback index. */
712 io_ret = ops->read_rollback_index(
713 ops, rollback_index_location, &stored_rollback_index);
714 if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
715 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
716 goto out;
717 } else if (io_ret != AVB_IO_RESULT_OK) {
718 avb_errorv(full_partition_name,
719 ": Error getting rollback index for location.\n",
720 NULL);
721 ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
722 goto out;
723 }
724 if (vbmeta_header.rollback_index < stored_rollback_index) {
725 avb_errorv(
726 full_partition_name,
727 ": Image rollback index is less than the stored rollback index.\n",
728 NULL);
729 ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
730 if (!allow_verification_error) {
731 goto out;
732 }
733 }
734
735 /* Copy vbmeta to vbmeta_images before recursing. */
736 if (is_main_vbmeta) {
737 avb_assert(slot_data->num_vbmeta_images == 0);
738 } else {
739 avb_assert(slot_data->num_vbmeta_images > 0);
740 }
741 if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
742 avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
743 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
744 goto out;
745 }
746 vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
747 vbmeta_image_data->partition_name = avb_strdup(partition_name);
748 vbmeta_image_data->vbmeta_data = vbmeta_buf;
749 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
750 * and this includes data past the end of the image. Pass the
751 * actual size of the vbmeta image. Also, no need to use
752 * avb_safe_add() since the header has already been verified.
753 */
754 vbmeta_image_data->vbmeta_size =
755 sizeof(AvbVBMetaImageHeader) +
756 vbmeta_header.authentication_data_block_size +
757 vbmeta_header.auxiliary_data_block_size;
758 vbmeta_image_data->verify_result = vbmeta_ret;
759
760 /* If verification has been disabled by setting a bit in the image,
761 * we're done... except that we need to load the entirety of the
762 * requested partitions.
763 */
764 if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
765 AvbSlotVerifyResult sub_ret;
766 avb_debugv(
767 full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
768 /* If load_requested_partitions() fail it is always a fatal
769 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
770 * than recoverable (e.g. one where result_should_continue()
771 * returns true) and we want to convey that error.
772 */
773 sub_ret = load_requested_partitions(
774 ops, requested_partitions, ab_suffix, slot_data);
775 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
776 ret = sub_ret;
777 }
778 goto out;
779 }
780
781 /* Now go through all descriptors and take the appropriate action:
782 *
783 * - hash descriptor: Load data from partition, calculate hash, and
784 * checks that it matches what's in the hash descriptor.
785 *
786 * - hashtree descriptor: Do nothing since verification happens
787 * on-the-fly from within the OS. (Unless the descriptor uses a
788 * persistent digest, in which case we need to find it).
789 *
790 * - chained partition descriptor: Load the footer, load the vbmeta
791 * image, verify vbmeta image (includes rollback checks, hash
792 * checks, bail on chained partitions).
793 */
794 descriptors =
795 avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
796 for (n = 0; n < num_descriptors; n++) {
797 AvbDescriptor desc;
798
799 if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
800 avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
801 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
802 goto out;
803 }
804
805 switch (desc.tag) {
806 case AVB_DESCRIPTOR_TAG_HASH: {
807 AvbSlotVerifyResult sub_ret;
808 sub_ret = load_and_verify_hash_partition(ops,
809 requested_partitions,
810 ab_suffix,
811 allow_verification_error,
812 descriptors[n],
813 slot_data);
814 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
815 ret = sub_ret;
816 if (!allow_verification_error || !result_should_continue(ret)) {
817 goto out;
818 }
819 }
820 } break;
821
822 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
823 AvbSlotVerifyResult sub_ret;
824 AvbChainPartitionDescriptor chain_desc;
825 const uint8_t* chain_partition_name;
826 const uint8_t* chain_public_key;
827
828 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
829 if (!is_main_vbmeta) {
830 avb_errorv(full_partition_name,
831 ": Encountered chain descriptor not in main image.\n",
832 NULL);
833 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
834 goto out;
835 }
836
837 if (!avb_chain_partition_descriptor_validate_and_byteswap(
838 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
839 avb_errorv(full_partition_name,
840 ": Chain partition descriptor is invalid.\n",
841 NULL);
842 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
843 goto out;
844 }
845
846 if (chain_desc.rollback_index_location == 0) {
847 avb_errorv(full_partition_name,
848 ": Chain partition has invalid "
849 "rollback_index_location field.\n",
850 NULL);
851 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
852 goto out;
853 }
854
855 chain_partition_name = ((const uint8_t*)descriptors[n]) +
856 sizeof(AvbChainPartitionDescriptor);
857 chain_public_key = chain_partition_name + chain_desc.partition_name_len;
858
859 sub_ret =
860 load_and_verify_vbmeta(ops,
861 requested_partitions,
862 ab_suffix,
863 allow_verification_error,
864 toplevel_vbmeta_flags,
865 chain_desc.rollback_index_location,
866 (const char*)chain_partition_name,
867 chain_desc.partition_name_len,
868 chain_public_key,
869 chain_desc.public_key_len,
870 slot_data,
871 NULL, /* out_algorithm_type */
872 NULL /* out_additional_cmdline_subst */);
873 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
874 ret = sub_ret;
875 if (!result_should_continue(ret)) {
876 goto out;
877 }
878 }
879 } break;
880
881 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
882 const uint8_t* kernel_cmdline;
883 AvbKernelCmdlineDescriptor kernel_cmdline_desc;
884 bool apply_cmdline;
885
886 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
887 (AvbKernelCmdlineDescriptor*)descriptors[n],
888 &kernel_cmdline_desc)) {
889 avb_errorv(full_partition_name,
890 ": Kernel cmdline descriptor is invalid.\n",
891 NULL);
892 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
893 goto out;
894 }
895
896 kernel_cmdline = ((const uint8_t*)descriptors[n]) +
897 sizeof(AvbKernelCmdlineDescriptor);
898
899 if (!avb_validate_utf8(kernel_cmdline,
900 kernel_cmdline_desc.kernel_cmdline_length)) {
901 avb_errorv(full_partition_name,
902 ": Kernel cmdline is not valid UTF-8.\n",
903 NULL);
904 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
905 goto out;
906 }
907
908 /* Compare the flags for top-level VBMeta struct with flags in
909 * the command-line descriptor so command-line snippets only
910 * intended for a certain mode (dm-verity enabled/disabled)
911 * are skipped if applicable.
912 */
913 apply_cmdline = true;
914 if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
915 if (kernel_cmdline_desc.flags &
916 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
917 apply_cmdline = false;
918 }
919 } else {
920 if (kernel_cmdline_desc.flags &
921 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
922 apply_cmdline = false;
923 }
924 }
925
926 if (apply_cmdline) {
927 if (slot_data->cmdline == NULL) {
928 slot_data->cmdline =
929 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
930 if (slot_data->cmdline == NULL) {
931 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
932 goto out;
933 }
934 avb_memcpy(slot_data->cmdline,
935 kernel_cmdline,
936 kernel_cmdline_desc.kernel_cmdline_length);
937 } else {
938 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
939 size_t orig_size = avb_strlen(slot_data->cmdline);
940 size_t new_size =
941 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
942 char* new_cmdline = avb_calloc(new_size);
943 if (new_cmdline == NULL) {
944 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
945 goto out;
946 }
947 avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
948 new_cmdline[orig_size] = ' ';
949 avb_memcpy(new_cmdline + orig_size + 1,
950 kernel_cmdline,
951 kernel_cmdline_desc.kernel_cmdline_length);
952 avb_free(slot_data->cmdline);
953 slot_data->cmdline = new_cmdline;
954 }
955 }
956 } break;
957
958 case AVB_DESCRIPTOR_TAG_HASHTREE: {
959 AvbHashtreeDescriptor hashtree_desc;
960
961 if (!avb_hashtree_descriptor_validate_and_byteswap(
962 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
963 avb_errorv(
964 full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
965 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
966 goto out;
967 }
968
969 /* We only need to continue when there is no digest in the descriptor.
970 * This is because the only processing here is to find the digest and
971 * make it available on the kernel command line.
972 */
973 if (hashtree_desc.root_digest_len == 0) {
974 char part_name[AVB_PART_NAME_MAX_SIZE];
975 size_t digest_len = 0;
976 uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
977 const uint8_t* desc_partition_name =
978 ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
979
980 if (!avb_validate_utf8(desc_partition_name,
981 hashtree_desc.partition_name_len)) {
982 avb_error("Partition name is not valid UTF-8.\n");
983 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
984 goto out;
985 }
986
987 /* No ab_suffix for partitions without a digest in the descriptor
988 * because these partitions hold data unique to this device and are
989 * not updated using an A/B scheme.
990 */
991 if ((hashtree_desc.flags &
992 AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
993 avb_strlen(ab_suffix) != 0) {
994 avb_error("Cannot use A/B with a persistent root digest.\n");
995 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
996 goto out;
997 }
998 if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
999 avb_error("Partition name does not fit.\n");
1000 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1001 goto out;
1002 }
1003 avb_memcpy(
1004 part_name, desc_partition_name, hashtree_desc.partition_name_len);
1005 part_name[hashtree_desc.partition_name_len] = '\0';
1006
1007 /* Determine the expected digest size from the hash algorithm. */
1008 if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1009 0) {
1010 digest_len = AVB_SHA1_DIGEST_SIZE;
1011 } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1012 "sha256") == 0) {
1013 digest_len = AVB_SHA256_DIGEST_SIZE;
1014 } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1015 "sha512") == 0) {
1016 digest_len = AVB_SHA512_DIGEST_SIZE;
1017 } else {
1018 avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1019 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1020 goto out;
1021 }
1022
1023 ret = read_persistent_digest(ops, part_name, digest_len, digest_buf);
1024 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1025 goto out;
1026 }
1027
1028 if (out_additional_cmdline_subst) {
1029 ret =
1030 avb_add_root_digest_substitution(part_name,
1031 digest_buf,
1032 digest_len,
1033 out_additional_cmdline_subst);
1034 if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1035 goto out;
1036 }
1037 }
1038 }
1039 } break;
1040
1041 case AVB_DESCRIPTOR_TAG_PROPERTY:
1042 /* Do nothing. */
1043 break;
1044 }
1045 }
1046
1047 if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1048 avb_errorv(
1049 full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1050 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1051 goto out;
1052 }
1053
1054 slot_data->rollback_indexes[rollback_index_location] =
1055 vbmeta_header.rollback_index;
1056
1057 if (out_algorithm_type != NULL) {
1058 *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1059 }
1060
1061out:
1062 /* If |vbmeta_image_data| isn't NULL it means that it adopted
1063 * |vbmeta_buf| so in that case don't free it here.
1064 */
1065 if (vbmeta_image_data == NULL) {
1066 if (vbmeta_buf != NULL) {
1067 avb_free(vbmeta_buf);
1068 }
1069 }
1070 if (descriptors != NULL) {
1071 avb_free(descriptors);
1072 }
1073 return ret;
1074}
1075
1076AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1077 const char* const* requested_partitions,
1078 const char* ab_suffix,
1079 AvbSlotVerifyFlags flags,
1080 AvbHashtreeErrorMode hashtree_error_mode,
1081 AvbSlotVerifyData** out_data) {
1082 AvbSlotVerifyResult ret;
1083 AvbSlotVerifyData* slot_data = NULL;
1084 AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1085 bool using_boot_for_vbmeta = false;
1086 AvbVBMetaImageHeader toplevel_vbmeta;
1087 bool allow_verification_error =
1088 (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1089 AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1090
1091 /* Fail early if we're missing the AvbOps needed for slot verification.
1092 *
1093 * For now, handle get_size_of_partition() not being implemented. In
1094 * a later release we may change that.
1095 */
1096 avb_assert(ops->read_is_device_unlocked != NULL);
1097 avb_assert(ops->read_from_partition != NULL);
1098 avb_assert(ops->validate_vbmeta_public_key != NULL);
1099 avb_assert(ops->read_rollback_index != NULL);
1100 avb_assert(ops->get_unique_guid_for_partition != NULL);
1101
1102 if (out_data != NULL) {
1103 *out_data = NULL;
1104 }
1105
1106 /* Allowing dm-verity errors defeats the purpose of verified boot so
1107 * only allow this if set up to allow verification errors
1108 * (e.g. typically only UNLOCKED mode).
1109 */
1110 if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1111 !allow_verification_error) {
1112 ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1113 goto fail;
1114 }
1115
1116 slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1117 if (slot_data == NULL) {
1118 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1119 goto fail;
1120 }
1121 slot_data->vbmeta_images =
1122 avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1123 if (slot_data->vbmeta_images == NULL) {
1124 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1125 goto fail;
1126 }
1127 slot_data->loaded_partitions =
1128 avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1129 if (slot_data->loaded_partitions == NULL) {
1130 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1131 goto fail;
1132 }
1133
1134 additional_cmdline_subst = avb_new_cmdline_subst_list();
1135 if (additional_cmdline_subst == NULL) {
1136 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1137 goto fail;
1138 }
1139
1140 ret = load_and_verify_vbmeta(ops,
1141 requested_partitions,
1142 ab_suffix,
1143 allow_verification_error,
1144 0 /* toplevel_vbmeta_flags */,
1145 0 /* rollback_index_location */,
1146 "vbmeta",
1147 avb_strlen("vbmeta"),
1148 NULL /* expected_public_key */,
1149 0 /* expected_public_key_length */,
1150 slot_data,
1151 &algorithm_type,
1152 additional_cmdline_subst);
1153 if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1154 goto fail;
1155 }
1156
1157 /* If things check out, mangle the kernel command-line as needed. */
1158 if (result_should_continue(ret)) {
1159 if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1160 avb_assert(
1161 avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1162 using_boot_for_vbmeta = true;
1163 }
1164
1165 /* Byteswap top-level vbmeta header since we'll need it below. */
1166 avb_vbmeta_image_header_to_host_byte_order(
1167 (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1168 &toplevel_vbmeta);
1169
1170 /* Fill in |ab_suffix| field. */
1171 slot_data->ab_suffix = avb_strdup(ab_suffix);
1172 if (slot_data->ab_suffix == NULL) {
1173 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1174 goto fail;
1175 }
1176
1177 /* If verification is disabled, we are done ... we specifically
1178 * don't want to add any androidboot.* options since verification
1179 * is disabled.
1180 */
1181 if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1182 /* Since verification is disabled we didn't process any
1183 * descriptors and thus there's no cmdline... so set root= such
1184 * that the system partition is mounted.
1185 */
1186 avb_assert(slot_data->cmdline == NULL);
1187 slot_data->cmdline =
1188 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1189 if (slot_data->cmdline == NULL) {
1190 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1191 goto fail;
1192 }
1193 } else {
1194 /* Add options - any failure in avb_append_options() is either an
1195 * I/O or OOM error.
1196 */
1197 AvbSlotVerifyResult sub_ret = avb_append_options(ops,
1198 slot_data,
1199 &toplevel_vbmeta,
1200 algorithm_type,
1201 hashtree_error_mode);
1202 if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1203 ret = sub_ret;
1204 goto fail;
1205 }
1206 }
1207
1208 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1209 if (slot_data->cmdline != NULL) {
1210 char* new_cmdline;
1211 new_cmdline = avb_sub_cmdline(ops,
1212 slot_data->cmdline,
1213 ab_suffix,
1214 using_boot_for_vbmeta,
1215 additional_cmdline_subst);
1216 if (new_cmdline != slot_data->cmdline) {
1217 if (new_cmdline == NULL) {
1218 ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1219 goto fail;
1220 }
1221 avb_free(slot_data->cmdline);
1222 slot_data->cmdline = new_cmdline;
1223 }
1224 }
1225
1226 if (out_data != NULL) {
1227 *out_data = slot_data;
1228 } else {
1229 avb_slot_verify_data_free(slot_data);
1230 }
1231 }
1232
1233 avb_free_cmdline_subst_list(additional_cmdline_subst);
1234 additional_cmdline_subst = NULL;
1235
1236 if (!allow_verification_error) {
1237 avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1238 }
1239
1240 return ret;
1241
1242fail:
1243 if (slot_data != NULL) {
1244 avb_slot_verify_data_free(slot_data);
1245 }
1246 if (additional_cmdline_subst != NULL) {
1247 avb_free_cmdline_subst_list(additional_cmdline_subst);
1248 }
1249 return ret;
1250}
1251
1252void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1253 if (data->ab_suffix != NULL) {
1254 avb_free(data->ab_suffix);
1255 }
1256 if (data->cmdline != NULL) {
1257 avb_free(data->cmdline);
1258 }
1259 if (data->vbmeta_images != NULL) {
1260 size_t n;
1261 for (n = 0; n < data->num_vbmeta_images; n++) {
1262 AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1263 if (vbmeta_image->partition_name != NULL) {
1264 avb_free(vbmeta_image->partition_name);
1265 }
1266 if (vbmeta_image->vbmeta_data != NULL) {
1267 avb_free(vbmeta_image->vbmeta_data);
1268 }
1269 }
1270 avb_free(data->vbmeta_images);
1271 }
1272 if (data->loaded_partitions != NULL) {
1273 size_t n;
1274 for (n = 0; n < data->num_loaded_partitions; n++) {
1275 AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1276 if (loaded_partition->partition_name != NULL) {
1277 avb_free(loaded_partition->partition_name);
1278 }
1279 if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1280 avb_free(loaded_partition->data);
1281 }
1282 }
1283 avb_free(data->loaded_partitions);
1284 }
1285 avb_free(data);
1286}
1287
1288const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1289 const char* ret = NULL;
1290
1291 switch (result) {
1292 case AVB_SLOT_VERIFY_RESULT_OK:
1293 ret = "OK";
1294 break;
1295 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1296 ret = "ERROR_OOM";
1297 break;
1298 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1299 ret = "ERROR_IO";
1300 break;
1301 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1302 ret = "ERROR_VERIFICATION";
1303 break;
1304 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1305 ret = "ERROR_ROLLBACK_INDEX";
1306 break;
1307 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1308 ret = "ERROR_PUBLIC_KEY_REJECTED";
1309 break;
1310 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1311 ret = "ERROR_INVALID_METADATA";
1312 break;
1313 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1314 ret = "ERROR_UNSUPPORTED_VERSION";
1315 break;
1316 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1317 ret = "ERROR_INVALID_ARGUMENT";
1318 break;
1319 /* Do not add a 'default:' case here because of -Wswitch. */
1320 }
1321
1322 if (ret == NULL) {
1323 avb_error("Unknown AvbSlotVerifyResult value.\n");
1324 ret = "(unknown)";
1325 }
1326
1327 return ret;
1328}
1329
1330void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
1331 AvbDigestType digest_type,
1332 uint8_t* out_digest) {
1333 bool ret = false;
1334 size_t n;
1335
1336 switch (digest_type) {
1337 case AVB_DIGEST_TYPE_SHA256: {
1338 AvbSHA256Ctx ctx;
1339 avb_sha256_init(&ctx);
1340 for (n = 0; n < data->num_vbmeta_images; n++) {
1341 avb_sha256_update(&ctx,
1342 data->vbmeta_images[n].vbmeta_data,
1343 data->vbmeta_images[n].vbmeta_size);
1344 }
1345 avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
1346 ret = true;
1347 } break;
1348
1349 case AVB_DIGEST_TYPE_SHA512: {
1350 AvbSHA512Ctx ctx;
1351 avb_sha512_init(&ctx);
1352 for (n = 0; n < data->num_vbmeta_images; n++) {
1353 avb_sha512_update(&ctx,
1354 data->vbmeta_images[n].vbmeta_data,
1355 data->vbmeta_images[n].vbmeta_size);
1356 }
1357 avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
1358 ret = true;
1359 } break;
1360
1361 /* Do not add a 'default:' case here because of -Wswitch. */
1362 }
1363
1364 if (!ret) {
1365 avb_fatal("Unknown digest type");
1366 }
1367}