1 // SPDX-License-Identifier: MIT
3 * Copyright (C) 2016 The Android Open Source Project
6 #include "avb_slot_verify.h"
7 #include "avb_chain_partition_descriptor.h"
8 #include "avb_cmdline.h"
9 #include "avb_footer.h"
10 #include "avb_hash_descriptor.h"
11 #include "avb_hashtree_descriptor.h"
12 #include "avb_kernel_cmdline_descriptor.h"
15 #include "avb_vbmeta_image.h"
16 #include "avb_version.h"
19 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
20 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
22 /* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
23 #define MAX_NUMBER_OF_VBMETA_IMAGES 32
25 /* Maximum size of a vbmeta image - 64 KiB. */
26 #define VBMETA_MAX_SIZE (64 * 1024)
28 static AvbSlotVerifyResult
initialize_persistent_digest(
30 const char* part_name
,
31 const char* persistent_value_name
,
33 const uint8_t* initial_digest
,
36 /* Helper function to see if we should continue with verification in
37 * allow_verification_error=true mode if something goes wrong. See the
38 * comments for the avb_slot_verify() function for more information.
40 static inline bool result_should_continue(AvbSlotVerifyResult result
) {
42 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM
:
43 case AVB_SLOT_VERIFY_RESULT_ERROR_IO
:
44 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
:
45 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
:
46 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
:
49 case AVB_SLOT_VERIFY_RESULT_OK
:
50 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
:
51 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
:
52 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
:
59 static AvbSlotVerifyResult
load_full_partition(AvbOps
* ops
,
60 const char* part_name
,
62 uint8_t** out_image_buf
,
63 bool* out_image_preloaded
) {
67 /* Make sure that we do not overwrite existing data. */
68 avb_assert(*out_image_buf
== NULL
);
69 avb_assert(!*out_image_preloaded
);
71 /* We are going to implicitly cast image_size from uint64_t to size_t in the
72 * following code, so we need to make sure that the cast is safe. */
73 if (image_size
!= (size_t)(image_size
)) {
74 avb_errorv(part_name
, ": Partition size too large to load.\n", NULL
);
75 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
78 /* Try use a preloaded one. */
79 if (ops
->get_preloaded_partition
!= NULL
) {
80 io_ret
= ops
->get_preloaded_partition(
81 ops
, part_name
, image_size
, out_image_buf
, &part_num_read
);
82 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
83 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
84 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
85 avb_errorv(part_name
, ": Error loading data from partition.\n", NULL
);
86 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
89 if (*out_image_buf
!= NULL
) {
90 if (part_num_read
!= image_size
) {
91 avb_errorv(part_name
, ": Read incorrect number of bytes.\n", NULL
);
92 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
94 *out_image_preloaded
= true;
98 /* Allocate and copy the partition. */
99 if (!*out_image_preloaded
) {
100 *out_image_buf
= avb_malloc(image_size
);
101 if (*out_image_buf
== NULL
) {
102 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
105 io_ret
= ops
->read_from_partition(ops
,
111 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
112 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
113 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
114 avb_errorv(part_name
, ": Error loading data from partition.\n", NULL
);
115 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
117 if (part_num_read
!= image_size
) {
118 avb_errorv(part_name
, ": Read incorrect number of bytes.\n", NULL
);
119 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
123 return AVB_SLOT_VERIFY_RESULT_OK
;
126 /* Reads a persistent digest stored as a named persistent value corresponding to
127 * the given |part_name|. The value is returned in |out_digest| which must point
128 * to |expected_digest_size| bytes. If there is no digest stored for |part_name|
129 * it can be initialized by providing a non-NULL |initial_digest| of length
130 * |expected_digest_size|. This automatic initialization will only occur if the
131 * device is currently locked. The |initial_digest| may be NULL.
133 * Returns AVB_SLOT_VERIFY_RESULT_OK on success, otherwise returns an
134 * AVB_SLOT_VERIFY_RESULT_ERROR_* error code.
136 * If the value does not exist, is not supported, or is not populated, and
137 * |initial_digest| is NULL, returns
138 * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA. If |expected_digest_size| does
139 * not match the stored digest size, also returns
140 * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA.
142 static AvbSlotVerifyResult
read_persistent_digest(AvbOps
* ops
,
143 const char* part_name
,
144 size_t expected_digest_size
,
145 const uint8_t* initial_digest
,
146 uint8_t* out_digest
) {
147 char* persistent_value_name
= NULL
;
148 AvbIOResult io_ret
= AVB_IO_RESULT_OK
;
149 size_t stored_digest_size
= 0;
151 if (ops
->read_persistent_value
== NULL
) {
152 avb_errorv(part_name
, ": Persistent values are not implemented.\n", NULL
);
153 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
155 persistent_value_name
=
156 avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX
, part_name
, NULL
);
157 if (persistent_value_name
== NULL
) {
158 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
161 io_ret
= ops
->read_persistent_value(ops
,
162 persistent_value_name
,
163 expected_digest_size
,
165 &stored_digest_size
);
167 // If no such named persistent value exists and an initial digest value was
168 // given, initialize the named persistent value with the given digest. If
169 // initialized successfully, this will recurse into this function but with a
170 // NULL initial_digest.
171 if (io_ret
== AVB_IO_RESULT_ERROR_NO_SUCH_VALUE
&& initial_digest
) {
172 AvbSlotVerifyResult ret
=
173 initialize_persistent_digest(ops
,
175 persistent_value_name
,
176 expected_digest_size
,
179 avb_free(persistent_value_name
);
182 avb_free(persistent_value_name
);
184 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
185 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
186 } else if (io_ret
== AVB_IO_RESULT_ERROR_NO_SUCH_VALUE
) {
187 // Treat a missing persistent value as a verification error, which is
188 // ignoreable, rather than a metadata error which is not.
189 avb_errorv(part_name
, ": Persistent digest does not exist.\n", NULL
);
190 return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
;
191 } else if (io_ret
== AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE
||
192 io_ret
== AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE
) {
194 part_name
, ": Persistent digest is not of expected size.\n", NULL
);
195 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
196 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
197 avb_errorv(part_name
, ": Error reading persistent digest.\n", NULL
);
198 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
199 } else if (expected_digest_size
!= stored_digest_size
) {
201 part_name
, ": Persistent digest is not of expected size.\n", NULL
);
202 return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
204 return AVB_SLOT_VERIFY_RESULT_OK
;
207 static AvbSlotVerifyResult
initialize_persistent_digest(
209 const char* part_name
,
210 const char* persistent_value_name
,
212 const uint8_t* initial_digest
,
213 uint8_t* out_digest
) {
214 AvbSlotVerifyResult ret
;
215 AvbIOResult io_ret
= AVB_IO_RESULT_OK
;
216 bool is_device_unlocked
= true;
218 io_ret
= ops
->read_is_device_unlocked(ops
, &is_device_unlocked
);
219 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
220 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
221 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
222 avb_error("Error getting device lock state.\n");
223 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
226 if (is_device_unlocked
) {
227 avb_debugv(part_name
,
228 ": Digest does not exist, device unlocked so not initializing "
231 return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
;
234 // Device locked; initialize digest with given initial value.
235 avb_debugv(part_name
,
236 ": Digest does not exist, initializing persistent digest.\n",
238 io_ret
= ops
->write_persistent_value(
239 ops
, persistent_value_name
, digest_size
, initial_digest
);
240 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
241 return AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
242 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
243 avb_errorv(part_name
, ": Error initializing persistent digest.\n", NULL
);
244 return AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
247 // To ensure that the digest value was written successfully - and avoid a
248 // scenario where the digest is simply 'initialized' on every verify - recurse
249 // into read_persistent_digest to read back the written value. The NULL
250 // initial_digest ensures that this will not recurse again.
251 ret
= read_persistent_digest(ops
, part_name
, digest_size
, NULL
, out_digest
);
252 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
253 avb_errorv(part_name
,
254 ": Reading back initialized persistent digest failed!\n",
260 static AvbSlotVerifyResult
load_and_verify_hash_partition(
262 const char* const* requested_partitions
,
263 const char* ab_suffix
,
264 bool allow_verification_error
,
265 const AvbDescriptor
* descriptor
,
266 AvbSlotVerifyData
* slot_data
) {
267 AvbHashDescriptor hash_desc
;
268 const uint8_t* desc_partition_name
= NULL
;
269 const uint8_t* desc_salt
;
270 const uint8_t* desc_digest
;
271 char part_name
[AVB_PART_NAME_MAX_SIZE
];
272 AvbSlotVerifyResult ret
;
274 uint8_t* image_buf
= NULL
;
275 bool image_preloaded
= false;
280 size_t expected_digest_len
= 0;
281 uint8_t expected_digest_buf
[AVB_SHA512_DIGEST_SIZE
];
282 const uint8_t* expected_digest
= NULL
;
284 if (!avb_hash_descriptor_validate_and_byteswap(
285 (const AvbHashDescriptor
*)descriptor
, &hash_desc
)) {
286 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
290 desc_partition_name
=
291 ((const uint8_t*)descriptor
) + sizeof(AvbHashDescriptor
);
292 desc_salt
= desc_partition_name
+ hash_desc
.partition_name_len
;
293 desc_digest
= desc_salt
+ hash_desc
.salt_len
;
295 if (!avb_validate_utf8(desc_partition_name
, hash_desc
.partition_name_len
)) {
296 avb_error("Partition name is not valid UTF-8.\n");
297 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
301 /* Don't bother loading or validating unless the partition was
302 * requested in the first place.
304 found
= avb_strv_find_str(requested_partitions
,
305 (const char*)desc_partition_name
,
306 hash_desc
.partition_name_len
);
308 ret
= AVB_SLOT_VERIFY_RESULT_OK
;
312 if ((hash_desc
.flags
& AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB
) != 0) {
313 /* No ab_suffix, just copy the partition name as is. */
314 if (hash_desc
.partition_name_len
>= AVB_PART_NAME_MAX_SIZE
) {
315 avb_error("Partition name does not fit.\n");
316 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
319 avb_memcpy(part_name
, desc_partition_name
, hash_desc
.partition_name_len
);
320 part_name
[hash_desc
.partition_name_len
] = '\0';
321 } else if (hash_desc
.digest_len
== 0 && avb_strlen(ab_suffix
) != 0) {
322 /* No ab_suffix allowed for partitions without a digest in the descriptor
323 * because these partitions hold data unique to this device and are not
324 * updated using an A/B scheme.
326 avb_error("Cannot use A/B with a persistent digest.\n");
327 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
330 /* Add ab_suffix to the partition name. */
331 if (!avb_str_concat(part_name
,
333 (const char*)desc_partition_name
,
334 hash_desc
.partition_name_len
,
336 avb_strlen(ab_suffix
))) {
337 avb_error("Partition name and suffix does not fit.\n");
338 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
343 /* If we're allowing verification errors then hash_desc.image_size
344 * may no longer match what's in the partition... so in this case
345 * just load the entire partition.
347 * For example, this can happen if a developer does 'fastboot flash
348 * boot /path/to/new/and/bigger/boot.img'. We want this to work
349 * since it's such a common workflow.
351 image_size
= hash_desc
.image_size
;
352 if (allow_verification_error
) {
353 io_ret
= ops
->get_size_of_partition(ops
, part_name
, &image_size
);
354 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
355 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
357 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
358 avb_errorv(part_name
, ": Error determining partition size.\n", NULL
);
359 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
362 avb_debugv(part_name
, ": Loading entire partition.\n", NULL
);
365 ret
= load_full_partition(
366 ops
, part_name
, image_size
, &image_buf
, &image_preloaded
);
367 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
370 // Although only one of the type might be used, we have to defined the
371 // structure here so that they would live outside the 'if/else' scope to be
373 AvbSHA256Ctx sha256_ctx
;
374 AvbSHA512Ctx sha512_ctx
;
375 size_t image_size_to_hash
= hash_desc
.image_size
;
376 // If we allow verification error and the whole partition is smaller than
377 // image size in hash descriptor, we just hash the whole partition.
378 if (image_size_to_hash
> image_size
) {
379 image_size_to_hash
= image_size
;
381 if (avb_strcmp((const char*)hash_desc
.hash_algorithm
, "sha256") == 0) {
382 avb_sha256_init(&sha256_ctx
);
383 avb_sha256_update(&sha256_ctx
, desc_salt
, hash_desc
.salt_len
);
384 avb_sha256_update(&sha256_ctx
, image_buf
, image_size_to_hash
);
385 digest
= avb_sha256_final(&sha256_ctx
);
386 digest_len
= AVB_SHA256_DIGEST_SIZE
;
387 } else if (avb_strcmp((const char*)hash_desc
.hash_algorithm
, "sha512") == 0) {
388 avb_sha512_init(&sha512_ctx
);
389 avb_sha512_update(&sha512_ctx
, desc_salt
, hash_desc
.salt_len
);
390 avb_sha512_update(&sha512_ctx
, image_buf
, image_size_to_hash
);
391 digest
= avb_sha512_final(&sha512_ctx
);
392 digest_len
= AVB_SHA512_DIGEST_SIZE
;
394 avb_errorv(part_name
, ": Unsupported hash algorithm.\n", NULL
);
395 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
399 if (hash_desc
.digest_len
== 0) {
400 /* Expect a match to a persistent digest. */
401 avb_debugv(part_name
, ": No digest, using persistent digest.\n", NULL
);
402 expected_digest_len
= digest_len
;
403 expected_digest
= expected_digest_buf
;
404 avb_assert(expected_digest_len
<= sizeof(expected_digest_buf
));
405 /* Pass |digest| as the |initial_digest| so devices not yet initialized get
406 * initialized to the current partition digest.
408 ret
= read_persistent_digest(
409 ops
, part_name
, digest_len
, digest
, expected_digest_buf
);
410 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
414 /* Expect a match to the digest in the descriptor. */
415 expected_digest_len
= hash_desc
.digest_len
;
416 expected_digest
= desc_digest
;
419 if (digest_len
!= expected_digest_len
) {
421 part_name
, ": Digest in descriptor not of expected size.\n", NULL
);
422 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
426 if (avb_safe_memcmp(digest
, expected_digest
, digest_len
) != 0) {
427 avb_errorv(part_name
,
428 ": Hash of data does not match digest in descriptor.\n",
430 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
;
434 ret
= AVB_SLOT_VERIFY_RESULT_OK
;
438 /* If it worked and something was loaded, copy to slot_data. */
439 if ((ret
== AVB_SLOT_VERIFY_RESULT_OK
|| result_should_continue(ret
)) &&
441 AvbPartitionData
* loaded_partition
;
442 if (slot_data
->num_loaded_partitions
== MAX_NUMBER_OF_LOADED_PARTITIONS
) {
443 avb_errorv(part_name
, ": Too many loaded partitions.\n", NULL
);
444 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
448 &slot_data
->loaded_partitions
[slot_data
->num_loaded_partitions
++];
449 loaded_partition
->partition_name
= avb_strdup(found
);
450 loaded_partition
->data_size
= image_size
;
451 loaded_partition
->data
= image_buf
;
452 loaded_partition
->preloaded
= image_preloaded
;
457 if (image_buf
!= NULL
&& !image_preloaded
) {
463 static AvbSlotVerifyResult
load_requested_partitions(
465 const char* const* requested_partitions
,
466 const char* ab_suffix
,
467 AvbSlotVerifyData
* slot_data
) {
468 AvbSlotVerifyResult ret
;
469 uint8_t* image_buf
= NULL
;
470 bool image_preloaded
= false;
473 for (n
= 0; requested_partitions
[n
] != NULL
; n
++) {
474 char part_name
[AVB_PART_NAME_MAX_SIZE
];
477 AvbPartitionData
* loaded_partition
;
479 if (!avb_str_concat(part_name
,
481 requested_partitions
[n
],
482 avb_strlen(requested_partitions
[n
]),
484 avb_strlen(ab_suffix
))) {
485 avb_error("Partition name and suffix does not fit.\n");
486 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
490 io_ret
= ops
->get_size_of_partition(ops
, part_name
, &image_size
);
491 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
492 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
494 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
495 avb_errorv(part_name
, ": Error determining partition size.\n", NULL
);
496 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
499 avb_debugv(part_name
, ": Loading entire partition.\n", NULL
);
501 ret
= load_full_partition(
502 ops
, part_name
, image_size
, &image_buf
, &image_preloaded
);
503 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
507 /* Move to slot_data. */
508 if (slot_data
->num_loaded_partitions
== MAX_NUMBER_OF_LOADED_PARTITIONS
) {
509 avb_errorv(part_name
, ": Too many loaded partitions.\n", NULL
);
510 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
514 &slot_data
->loaded_partitions
[slot_data
->num_loaded_partitions
++];
515 loaded_partition
->partition_name
= avb_strdup(requested_partitions
[n
]);
516 if (loaded_partition
->partition_name
== NULL
) {
517 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
520 loaded_partition
->data_size
= image_size
;
521 loaded_partition
->data
= image_buf
; /* Transferring the owner. */
522 loaded_partition
->preloaded
= image_preloaded
;
524 image_preloaded
= false;
527 ret
= AVB_SLOT_VERIFY_RESULT_OK
;
530 /* Free the current buffer if any. */
531 if (image_buf
!= NULL
&& !image_preloaded
) {
534 /* Buffers that are already saved in slot_data will be handled by the caller
535 * even on failure. */
539 static AvbSlotVerifyResult
load_and_verify_vbmeta(
541 const char* const* requested_partitions
,
542 const char* ab_suffix
,
543 AvbSlotVerifyFlags flags
,
544 bool allow_verification_error
,
545 AvbVBMetaImageFlags toplevel_vbmeta_flags
,
546 int rollback_index_location
,
547 const char* partition_name
,
548 size_t partition_name_len
,
549 const uint8_t* expected_public_key
,
550 size_t expected_public_key_length
,
551 AvbSlotVerifyData
* slot_data
,
552 AvbAlgorithmType
* out_algorithm_type
,
553 AvbCmdlineSubstList
* out_additional_cmdline_subst
) {
554 char full_partition_name
[AVB_PART_NAME_MAX_SIZE
];
555 AvbSlotVerifyResult ret
;
557 size_t vbmeta_offset
;
559 uint8_t* vbmeta_buf
= NULL
;
560 size_t vbmeta_num_read
;
561 AvbVBMetaVerifyResult vbmeta_ret
;
562 const uint8_t* pk_data
;
564 AvbVBMetaImageHeader vbmeta_header
;
565 uint64_t stored_rollback_index
;
566 const AvbDescriptor
** descriptors
= NULL
;
567 size_t num_descriptors
;
570 bool look_for_vbmeta_footer
;
571 AvbVBMetaData
* vbmeta_image_data
= NULL
;
573 ret
= AVB_SLOT_VERIFY_RESULT_OK
;
575 avb_assert(slot_data
!= NULL
);
577 /* Since we allow top-level vbmeta in 'boot', use
578 * rollback_index_location to determine whether we're the main
581 is_main_vbmeta
= false;
582 if (rollback_index_location
== 0) {
583 if ((flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
) == 0) {
584 is_main_vbmeta
= true;
588 /* Don't use footers for vbmeta partitions ('vbmeta' or
589 * 'vbmeta_<partition_name>').
591 look_for_vbmeta_footer
= true;
592 if (avb_strncmp(partition_name
, "vbmeta", avb_strlen("vbmeta")) == 0) {
593 look_for_vbmeta_footer
= false;
596 if (!avb_validate_utf8((const uint8_t*)partition_name
, partition_name_len
)) {
597 avb_error("Partition name is not valid UTF-8.\n");
598 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
602 /* Construct full partition name e.g. system_a. */
603 if (!avb_str_concat(full_partition_name
,
604 sizeof full_partition_name
,
608 avb_strlen(ab_suffix
))) {
609 avb_error("Partition name and suffix does not fit.\n");
610 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
614 /* If we're loading from the main vbmeta partition, the vbmeta struct is in
615 * the beginning. Otherwise we may have to locate it via a footer... if no
616 * footer is found, we look in the beginning to support e.g. vbmeta_<org>
617 * partitions holding data for e.g. super partitions (b/80195851 for
621 vbmeta_size
= VBMETA_MAX_SIZE
;
622 if (look_for_vbmeta_footer
) {
623 uint8_t footer_buf
[AVB_FOOTER_SIZE
];
624 size_t footer_num_read
;
627 io_ret
= ops
->read_from_partition(ops
,
633 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
634 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
636 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
637 avb_errorv(full_partition_name
, ": Error loading footer.\n", NULL
);
638 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
641 avb_assert(footer_num_read
== AVB_FOOTER_SIZE
);
643 if (!avb_footer_validate_and_byteswap((const AvbFooter
*)footer_buf
,
645 avb_debugv(full_partition_name
, ": No footer detected.\n", NULL
);
647 /* Basic footer sanity check since the data is untrusted. */
648 if (footer
.vbmeta_size
> VBMETA_MAX_SIZE
) {
650 full_partition_name
, ": Invalid vbmeta size in footer.\n", NULL
);
652 vbmeta_offset
= footer
.vbmeta_offset
;
653 vbmeta_size
= footer
.vbmeta_size
;
658 vbmeta_buf
= avb_malloc(vbmeta_size
);
659 if (vbmeta_buf
== NULL
) {
660 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
664 if (vbmeta_offset
!= 0) {
665 avb_debugv("Loading vbmeta struct in footer from partition '",
670 avb_debugv("Loading vbmeta struct from partition '",
676 io_ret
= ops
->read_from_partition(ops
,
682 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
683 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
685 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
686 /* If we're looking for 'vbmeta' but there is no such partition,
687 * go try to get it from the boot partition instead.
689 if (is_main_vbmeta
&& io_ret
== AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION
&&
690 !look_for_vbmeta_footer
) {
691 avb_debugv(full_partition_name
,
692 ": No such partition. Trying 'boot' instead.\n",
694 ret
= load_and_verify_vbmeta(ops
,
695 requested_partitions
,
698 allow_verification_error
,
699 0 /* toplevel_vbmeta_flags */,
700 0 /* rollback_index_location */,
703 NULL
/* expected_public_key */,
704 0 /* expected_public_key_length */,
707 out_additional_cmdline_subst
);
710 avb_errorv(full_partition_name
, ": Error loading vbmeta data.\n", NULL
);
711 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
715 avb_assert(vbmeta_num_read
<= vbmeta_size
);
717 /* Check if the image is properly signed and get the public key used
721 avb_vbmeta_image_verify(vbmeta_buf
, vbmeta_num_read
, &pk_data
, &pk_len
);
722 switch (vbmeta_ret
) {
723 case AVB_VBMETA_VERIFY_RESULT_OK
:
724 avb_assert(pk_data
!= NULL
&& pk_len
> 0);
727 case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED
:
728 case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH
:
729 case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH
:
730 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
;
731 avb_errorv(full_partition_name
,
732 ": Error verifying vbmeta image: ",
733 avb_vbmeta_verify_result_to_string(vbmeta_ret
),
736 if (!allow_verification_error
) {
741 case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER
:
742 /* No way to continue this case. */
743 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
744 avb_errorv(full_partition_name
,
745 ": Error verifying vbmeta image: invalid vbmeta header\n",
749 case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION
:
750 /* No way to continue this case. */
751 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
;
752 avb_errorv(full_partition_name
,
753 ": Error verifying vbmeta image: unsupported AVB version\n",
758 /* Byteswap the header. */
759 avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader
*)vbmeta_buf
,
762 /* If we're the toplevel, assign flags so they'll be passed down. */
763 if (is_main_vbmeta
) {
764 toplevel_vbmeta_flags
= (AvbVBMetaImageFlags
)vbmeta_header
.flags
;
766 if (vbmeta_header
.flags
!= 0) {
767 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
768 avb_errorv(full_partition_name
,
769 ": chained vbmeta image has non-zero flags\n",
775 uint32_t rollback_index_location_to_use
= rollback_index_location
;
777 /* Check if key used to make signature matches what is expected. */
778 if (pk_data
!= NULL
) {
779 if (expected_public_key
!= NULL
) {
780 avb_assert(!is_main_vbmeta
);
781 if (expected_public_key_length
!= pk_len
||
782 avb_safe_memcmp(expected_public_key
, pk_data
, pk_len
) != 0) {
783 avb_errorv(full_partition_name
,
784 ": Public key used to sign data does not match key in chain "
785 "partition descriptor.\n",
787 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
;
788 if (!allow_verification_error
) {
793 bool key_is_trusted
= false;
794 const uint8_t* pk_metadata
= NULL
;
795 size_t pk_metadata_len
= 0;
797 if (vbmeta_header
.public_key_metadata_size
> 0) {
798 pk_metadata
= vbmeta_buf
+ sizeof(AvbVBMetaImageHeader
) +
799 vbmeta_header
.authentication_data_block_size
+
800 vbmeta_header
.public_key_metadata_offset
;
801 pk_metadata_len
= vbmeta_header
.public_key_metadata_size
;
804 // If we're not using a vbmeta partition, need to use another AvbOps...
805 if (flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
) {
806 io_ret
= ops
->validate_public_key_for_partition(
814 &rollback_index_location_to_use
);
816 avb_assert(is_main_vbmeta
);
817 io_ret
= ops
->validate_vbmeta_public_key(ops
,
825 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
826 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
828 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
829 avb_errorv(full_partition_name
,
830 ": Error while checking public key used to sign data.\n",
832 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
835 if (!key_is_trusted
) {
836 avb_errorv(full_partition_name
,
837 ": Public key used to sign data rejected.\n",
839 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
;
840 if (!allow_verification_error
) {
847 /* Check rollback index. */
848 io_ret
= ops
->read_rollback_index(
849 ops
, rollback_index_location_to_use
, &stored_rollback_index
);
850 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
851 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
853 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
854 avb_errorv(full_partition_name
,
855 ": Error getting rollback index for location.\n",
857 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
860 if (vbmeta_header
.rollback_index
< stored_rollback_index
) {
863 ": Image rollback index is less than the stored rollback index.\n",
865 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
;
866 if (!allow_verification_error
) {
871 /* Copy vbmeta to vbmeta_images before recursing. */
872 if (is_main_vbmeta
) {
873 avb_assert(slot_data
->num_vbmeta_images
== 0);
875 if (!(flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
)) {
876 avb_assert(slot_data
->num_vbmeta_images
> 0);
879 if (slot_data
->num_vbmeta_images
== MAX_NUMBER_OF_VBMETA_IMAGES
) {
880 avb_errorv(full_partition_name
, ": Too many vbmeta images.\n", NULL
);
881 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
884 vbmeta_image_data
= &slot_data
->vbmeta_images
[slot_data
->num_vbmeta_images
++];
885 vbmeta_image_data
->partition_name
= avb_strdup(partition_name
);
886 vbmeta_image_data
->vbmeta_data
= vbmeta_buf
;
887 /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
888 * and this includes data past the end of the image. Pass the
889 * actual size of the vbmeta image. Also, no need to use
890 * avb_safe_add() since the header has already been verified.
892 vbmeta_image_data
->vbmeta_size
=
893 sizeof(AvbVBMetaImageHeader
) +
894 vbmeta_header
.authentication_data_block_size
+
895 vbmeta_header
.auxiliary_data_block_size
;
896 vbmeta_image_data
->verify_result
= vbmeta_ret
;
898 /* If verification has been disabled by setting a bit in the image,
899 * we're done... except that we need to load the entirety of the
900 * requested partitions.
902 if (vbmeta_header
.flags
& AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
) {
903 AvbSlotVerifyResult sub_ret
;
905 full_partition_name
, ": VERIFICATION_DISABLED bit is set.\n", NULL
);
906 /* If load_requested_partitions() fail it is always a fatal
907 * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
908 * than recoverable (e.g. one where result_should_continue()
909 * returns true) and we want to convey that error.
911 sub_ret
= load_requested_partitions(
912 ops
, requested_partitions
, ab_suffix
, slot_data
);
913 if (sub_ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
919 /* Now go through all descriptors and take the appropriate action:
921 * - hash descriptor: Load data from partition, calculate hash, and
922 * checks that it matches what's in the hash descriptor.
924 * - hashtree descriptor: Do nothing since verification happens
925 * on-the-fly from within the OS. (Unless the descriptor uses a
926 * persistent digest, in which case we need to find it).
928 * - chained partition descriptor: Load the footer, load the vbmeta
929 * image, verify vbmeta image (includes rollback checks, hash
930 * checks, bail on chained partitions).
933 avb_descriptor_get_all(vbmeta_buf
, vbmeta_num_read
, &num_descriptors
);
934 for (n
= 0; n
< num_descriptors
; n
++) {
937 if (!avb_descriptor_validate_and_byteswap(descriptors
[n
], &desc
)) {
938 avb_errorv(full_partition_name
, ": Descriptor is invalid.\n", NULL
);
939 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
944 case AVB_DESCRIPTOR_TAG_HASH
: {
945 AvbSlotVerifyResult sub_ret
;
946 sub_ret
= load_and_verify_hash_partition(ops
,
947 requested_partitions
,
949 allow_verification_error
,
952 if (sub_ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
954 if (!allow_verification_error
|| !result_should_continue(ret
)) {
960 case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION
: {
961 AvbSlotVerifyResult sub_ret
;
962 AvbChainPartitionDescriptor chain_desc
;
963 const uint8_t* chain_partition_name
;
964 const uint8_t* chain_public_key
;
966 /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
967 if (!is_main_vbmeta
) {
968 avb_errorv(full_partition_name
,
969 ": Encountered chain descriptor not in main image.\n",
971 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
975 if (!avb_chain_partition_descriptor_validate_and_byteswap(
976 (AvbChainPartitionDescriptor
*)descriptors
[n
], &chain_desc
)) {
977 avb_errorv(full_partition_name
,
978 ": Chain partition descriptor is invalid.\n",
980 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
984 if (chain_desc
.rollback_index_location
== 0) {
985 avb_errorv(full_partition_name
,
986 ": Chain partition has invalid "
987 "rollback_index_location field.\n",
989 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
993 chain_partition_name
= ((const uint8_t*)descriptors
[n
]) +
994 sizeof(AvbChainPartitionDescriptor
);
995 chain_public_key
= chain_partition_name
+ chain_desc
.partition_name_len
;
998 load_and_verify_vbmeta(ops
,
999 requested_partitions
,
1002 allow_verification_error
,
1003 toplevel_vbmeta_flags
,
1004 chain_desc
.rollback_index_location
,
1005 (const char*)chain_partition_name
,
1006 chain_desc
.partition_name_len
,
1008 chain_desc
.public_key_len
,
1010 NULL
, /* out_algorithm_type */
1011 NULL
/* out_additional_cmdline_subst */);
1012 if (sub_ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1014 if (!result_should_continue(ret
)) {
1020 case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE
: {
1021 const uint8_t* kernel_cmdline
;
1022 AvbKernelCmdlineDescriptor kernel_cmdline_desc
;
1025 if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
1026 (AvbKernelCmdlineDescriptor
*)descriptors
[n
],
1027 &kernel_cmdline_desc
)) {
1028 avb_errorv(full_partition_name
,
1029 ": Kernel cmdline descriptor is invalid.\n",
1031 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1035 kernel_cmdline
= ((const uint8_t*)descriptors
[n
]) +
1036 sizeof(AvbKernelCmdlineDescriptor
);
1038 if (!avb_validate_utf8(kernel_cmdline
,
1039 kernel_cmdline_desc
.kernel_cmdline_length
)) {
1040 avb_errorv(full_partition_name
,
1041 ": Kernel cmdline is not valid UTF-8.\n",
1043 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1047 /* Compare the flags for top-level VBMeta struct with flags in
1048 * the command-line descriptor so command-line snippets only
1049 * intended for a certain mode (dm-verity enabled/disabled)
1050 * are skipped if applicable.
1052 apply_cmdline
= true;
1053 if (toplevel_vbmeta_flags
& AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED
) {
1054 if (kernel_cmdline_desc
.flags
&
1055 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED
) {
1056 apply_cmdline
= false;
1059 if (kernel_cmdline_desc
.flags
&
1060 AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED
) {
1061 apply_cmdline
= false;
1065 if (apply_cmdline
) {
1066 if (slot_data
->cmdline
== NULL
) {
1067 slot_data
->cmdline
=
1068 avb_calloc(kernel_cmdline_desc
.kernel_cmdline_length
+ 1);
1069 if (slot_data
->cmdline
== NULL
) {
1070 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1073 avb_memcpy(slot_data
->cmdline
,
1075 kernel_cmdline_desc
.kernel_cmdline_length
);
1077 /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
1078 size_t orig_size
= avb_strlen(slot_data
->cmdline
);
1080 orig_size
+ 1 + kernel_cmdline_desc
.kernel_cmdline_length
+ 1;
1081 char* new_cmdline
= avb_calloc(new_size
);
1082 if (new_cmdline
== NULL
) {
1083 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1086 avb_memcpy(new_cmdline
, slot_data
->cmdline
, orig_size
);
1087 new_cmdline
[orig_size
] = ' ';
1088 avb_memcpy(new_cmdline
+ orig_size
+ 1,
1090 kernel_cmdline_desc
.kernel_cmdline_length
);
1091 avb_free(slot_data
->cmdline
);
1092 slot_data
->cmdline
= new_cmdline
;
1097 case AVB_DESCRIPTOR_TAG_HASHTREE
: {
1098 AvbHashtreeDescriptor hashtree_desc
;
1100 if (!avb_hashtree_descriptor_validate_and_byteswap(
1101 (AvbHashtreeDescriptor
*)descriptors
[n
], &hashtree_desc
)) {
1103 full_partition_name
, ": Hashtree descriptor is invalid.\n", NULL
);
1104 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1108 /* We only need to continue when there is no digest in the descriptor.
1109 * This is because the only processing here is to find the digest and
1110 * make it available on the kernel command line.
1112 if (hashtree_desc
.root_digest_len
== 0) {
1113 char part_name
[AVB_PART_NAME_MAX_SIZE
];
1114 size_t digest_len
= 0;
1115 uint8_t digest_buf
[AVB_SHA512_DIGEST_SIZE
];
1116 const uint8_t* desc_partition_name
=
1117 ((const uint8_t*)descriptors
[n
]) + sizeof(AvbHashtreeDescriptor
);
1119 if (!avb_validate_utf8(desc_partition_name
,
1120 hashtree_desc
.partition_name_len
)) {
1121 avb_error("Partition name is not valid UTF-8.\n");
1122 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1126 /* No ab_suffix for partitions without a digest in the descriptor
1127 * because these partitions hold data unique to this device and are
1128 * not updated using an A/B scheme.
1130 if ((hashtree_desc
.flags
&
1131 AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB
) == 0 &&
1132 avb_strlen(ab_suffix
) != 0) {
1133 avb_error("Cannot use A/B with a persistent root digest.\n");
1134 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1137 if (hashtree_desc
.partition_name_len
>= AVB_PART_NAME_MAX_SIZE
) {
1138 avb_error("Partition name does not fit.\n");
1139 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1143 part_name
, desc_partition_name
, hashtree_desc
.partition_name_len
);
1144 part_name
[hashtree_desc
.partition_name_len
] = '\0';
1146 /* Determine the expected digest size from the hash algorithm. */
1147 if (avb_strcmp((const char*)hashtree_desc
.hash_algorithm
, "sha1") ==
1149 digest_len
= AVB_SHA1_DIGEST_SIZE
;
1150 } else if (avb_strcmp((const char*)hashtree_desc
.hash_algorithm
,
1152 digest_len
= AVB_SHA256_DIGEST_SIZE
;
1153 } else if (avb_strcmp((const char*)hashtree_desc
.hash_algorithm
,
1155 digest_len
= AVB_SHA512_DIGEST_SIZE
;
1157 avb_errorv(part_name
, ": Unsupported hash algorithm.\n", NULL
);
1158 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1162 ret
= read_persistent_digest(ops
,
1165 NULL
/* initial_digest */,
1167 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1171 if (out_additional_cmdline_subst
) {
1173 avb_add_root_digest_substitution(part_name
,
1176 out_additional_cmdline_subst
);
1177 if (ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1184 case AVB_DESCRIPTOR_TAG_PROPERTY
:
1190 if (rollback_index_location
< 0 ||
1191 rollback_index_location
>= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS
) {
1193 full_partition_name
, ": Invalid rollback_index_location.\n", NULL
);
1194 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
;
1198 slot_data
->rollback_indexes
[rollback_index_location
] =
1199 vbmeta_header
.rollback_index
;
1201 if (out_algorithm_type
!= NULL
) {
1202 *out_algorithm_type
= (AvbAlgorithmType
)vbmeta_header
.algorithm_type
;
1206 /* If |vbmeta_image_data| isn't NULL it means that it adopted
1207 * |vbmeta_buf| so in that case don't free it here.
1209 if (vbmeta_image_data
== NULL
) {
1210 if (vbmeta_buf
!= NULL
) {
1211 avb_free(vbmeta_buf
);
1214 if (descriptors
!= NULL
) {
1215 avb_free(descriptors
);
1220 static AvbIOResult
avb_manage_hashtree_error_mode(
1222 AvbSlotVerifyFlags flags
,
1223 AvbSlotVerifyData
* data
,
1224 AvbHashtreeErrorMode
* out_hashtree_error_mode
) {
1225 AvbHashtreeErrorMode ret
= AVB_HASHTREE_ERROR_MODE_RESTART
;
1226 AvbIOResult io_ret
= AVB_IO_RESULT_OK
;
1227 uint8_t vbmeta_digest_sha256
[AVB_SHA256_DIGEST_SIZE
];
1228 uint8_t stored_vbmeta_digest_sha256
[AVB_SHA256_DIGEST_SIZE
];
1229 size_t num_bytes_read
;
1231 avb_assert(out_hashtree_error_mode
!= NULL
);
1232 avb_assert(ops
->read_persistent_value
!= NULL
);
1233 avb_assert(ops
->write_persistent_value
!= NULL
);
1235 // If we're rebooting because of dm-verity corruption, make a note of
1236 // the vbmeta hash so we can stay in 'eio' mode until things change.
1237 if (flags
& AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION
) {
1239 "Rebooting because of dm-verity corruption - "
1240 "recording OS instance and using 'eio' mode.\n");
1241 avb_slot_verify_data_calculate_vbmeta_digest(
1242 data
, AVB_DIGEST_TYPE_SHA256
, vbmeta_digest_sha256
);
1243 io_ret
= ops
->write_persistent_value(ops
,
1244 AVB_NPV_MANAGED_VERITY_MODE
,
1245 AVB_SHA256_DIGEST_SIZE
,
1246 vbmeta_digest_sha256
);
1247 if (io_ret
!= AVB_IO_RESULT_OK
) {
1248 avb_error("Error writing to " AVB_NPV_MANAGED_VERITY_MODE
".\n");
1251 ret
= AVB_HASHTREE_ERROR_MODE_EIO
;
1252 io_ret
= AVB_IO_RESULT_OK
;
1256 // See if we're in 'eio' mode.
1257 io_ret
= ops
->read_persistent_value(ops
,
1258 AVB_NPV_MANAGED_VERITY_MODE
,
1259 AVB_SHA256_DIGEST_SIZE
,
1260 stored_vbmeta_digest_sha256
,
1262 if (io_ret
== AVB_IO_RESULT_ERROR_NO_SUCH_VALUE
||
1263 (io_ret
== AVB_IO_RESULT_OK
&& num_bytes_read
== 0)) {
1264 // This is the usual case ('eio' mode not set).
1265 avb_debug("No dm-verity corruption - using in 'restart' mode.\n");
1266 ret
= AVB_HASHTREE_ERROR_MODE_RESTART
;
1267 io_ret
= AVB_IO_RESULT_OK
;
1269 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
1270 avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE
".\n");
1273 if (num_bytes_read
!= AVB_SHA256_DIGEST_SIZE
) {
1275 "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
1277 io_ret
= AVB_IO_RESULT_ERROR_IO
;
1281 // OK, so we're currently in 'eio' mode and the vbmeta digest of the OS
1282 // that caused this is in |stored_vbmeta_digest_sha256| ... now see if
1283 // the OS we're dealing with now is the same.
1284 avb_slot_verify_data_calculate_vbmeta_digest(
1285 data
, AVB_DIGEST_TYPE_SHA256
, vbmeta_digest_sha256
);
1286 if (avb_memcmp(vbmeta_digest_sha256
,
1287 stored_vbmeta_digest_sha256
,
1288 AVB_SHA256_DIGEST_SIZE
) == 0) {
1289 // It's the same so we're still in 'eio' mode.
1290 avb_debug("Same OS instance detected - staying in 'eio' mode.\n");
1291 ret
= AVB_HASHTREE_ERROR_MODE_EIO
;
1292 io_ret
= AVB_IO_RESULT_OK
;
1296 "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
1298 ops
->write_persistent_value(ops
,
1299 AVB_NPV_MANAGED_VERITY_MODE
,
1300 0, // This clears the persistent property.
1301 vbmeta_digest_sha256
);
1302 if (io_ret
!= AVB_IO_RESULT_OK
) {
1303 avb_error("Error clearing " AVB_NPV_MANAGED_VERITY_MODE
".\n");
1306 ret
= AVB_HASHTREE_ERROR_MODE_RESTART
;
1307 io_ret
= AVB_IO_RESULT_OK
;
1311 *out_hashtree_error_mode
= ret
;
1315 static bool has_system_partition(AvbOps
* ops
, const char* ab_suffix
) {
1316 char part_name
[AVB_PART_NAME_MAX_SIZE
];
1317 char* system_part_name
= "system";
1321 if (!avb_str_concat(part_name
,
1324 avb_strlen(system_part_name
),
1326 avb_strlen(ab_suffix
))) {
1327 avb_error("System partition name and suffix does not fit.\n");
1331 io_ret
= ops
->get_unique_guid_for_partition(
1332 ops
, part_name
, guid_buf
, sizeof guid_buf
);
1333 if (io_ret
== AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION
) {
1334 avb_debug("No system partition.\n");
1336 } else if (io_ret
!= AVB_IO_RESULT_OK
) {
1337 avb_error("Error getting unique GUID for system partition.\n");
1344 AvbSlotVerifyResult
avb_slot_verify(AvbOps
* ops
,
1345 const char* const* requested_partitions
,
1346 const char* ab_suffix
,
1347 AvbSlotVerifyFlags flags
,
1348 AvbHashtreeErrorMode hashtree_error_mode
,
1349 AvbSlotVerifyData
** out_data
) {
1350 AvbSlotVerifyResult ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
;
1351 AvbSlotVerifyData
* slot_data
= NULL
;
1352 AvbAlgorithmType algorithm_type
= AVB_ALGORITHM_TYPE_NONE
;
1353 bool using_boot_for_vbmeta
= false;
1354 AvbVBMetaImageHeader toplevel_vbmeta
;
1355 bool allow_verification_error
=
1356 (flags
& AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
);
1357 AvbCmdlineSubstList
* additional_cmdline_subst
= NULL
;
1359 /* Fail early if we're missing the AvbOps needed for slot verification. */
1360 avb_assert(ops
->read_is_device_unlocked
!= NULL
);
1361 avb_assert(ops
->read_from_partition
!= NULL
);
1362 avb_assert(ops
->get_size_of_partition
!= NULL
);
1363 avb_assert(ops
->read_rollback_index
!= NULL
);
1364 avb_assert(ops
->get_unique_guid_for_partition
!= NULL
);
1366 if (out_data
!= NULL
) {
1370 /* Allowing dm-verity errors defeats the purpose of verified boot so
1371 * only allow this if set up to allow verification errors
1372 * (e.g. typically only UNLOCKED mode).
1374 if (hashtree_error_mode
== AVB_HASHTREE_ERROR_MODE_LOGGING
&&
1375 !allow_verification_error
) {
1376 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
;
1380 /* Make sure passed-in AvbOps support persistent values if
1381 * asking for libavb to manage verity state.
1383 if (hashtree_error_mode
== AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
) {
1384 if (ops
->read_persistent_value
== NULL
||
1385 ops
->write_persistent_value
== NULL
) {
1387 "Persistent values required for "
1388 "AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO "
1389 "but are not implemented in given AvbOps.\n");
1390 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
;
1395 /* Make sure passed-in AvbOps support verifying public keys and getting
1396 * rollback index location if not using a vbmeta partition.
1398 if (flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
) {
1399 if (ops
->validate_public_key_for_partition
== NULL
) {
1401 "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
1402 "validate_public_key_for_partition() operation isn't implemented.\n");
1403 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
;
1407 avb_assert(ops
->validate_vbmeta_public_key
!= NULL
);
1410 slot_data
= avb_calloc(sizeof(AvbSlotVerifyData
));
1411 if (slot_data
== NULL
) {
1412 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1415 slot_data
->vbmeta_images
=
1416 avb_calloc(sizeof(AvbVBMetaData
) * MAX_NUMBER_OF_VBMETA_IMAGES
);
1417 if (slot_data
->vbmeta_images
== NULL
) {
1418 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1421 slot_data
->loaded_partitions
=
1422 avb_calloc(sizeof(AvbPartitionData
) * MAX_NUMBER_OF_LOADED_PARTITIONS
);
1423 if (slot_data
->loaded_partitions
== NULL
) {
1424 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1428 additional_cmdline_subst
= avb_new_cmdline_subst_list();
1429 if (additional_cmdline_subst
== NULL
) {
1430 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1434 if (flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
) {
1435 if (requested_partitions
== NULL
|| requested_partitions
[0] == NULL
) {
1437 "Requested partitions cannot be empty when using "
1438 "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
1439 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
;
1443 /* No vbmeta partition, go through each of the requested partitions... */
1444 for (size_t n
= 0; requested_partitions
[n
] != NULL
; n
++) {
1445 ret
= load_and_verify_vbmeta(ops
,
1446 requested_partitions
,
1449 allow_verification_error
,
1450 0 /* toplevel_vbmeta_flags */,
1451 0 /* rollback_index_location */,
1452 requested_partitions
[n
],
1453 avb_strlen(requested_partitions
[n
]),
1454 NULL
/* expected_public_key */,
1455 0 /* expected_public_key_length */,
1458 additional_cmdline_subst
);
1459 if (!allow_verification_error
&& ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1465 /* Usual path, load "vbmeta"... */
1466 ret
= load_and_verify_vbmeta(ops
,
1467 requested_partitions
,
1470 allow_verification_error
,
1471 0 /* toplevel_vbmeta_flags */,
1472 0 /* rollback_index_location */,
1474 avb_strlen("vbmeta"),
1475 NULL
/* expected_public_key */,
1476 0 /* expected_public_key_length */,
1479 additional_cmdline_subst
);
1480 if (!allow_verification_error
&& ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1485 if (!result_should_continue(ret
)) {
1489 /* If things check out, mangle the kernel command-line as needed. */
1490 if (!(flags
& AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION
)) {
1491 if (avb_strcmp(slot_data
->vbmeta_images
[0].partition_name
, "vbmeta") != 0) {
1493 avb_strcmp(slot_data
->vbmeta_images
[0].partition_name
, "boot") == 0);
1494 using_boot_for_vbmeta
= true;
1498 /* Byteswap top-level vbmeta header since we'll need it below. */
1499 avb_vbmeta_image_header_to_host_byte_order(
1500 (const AvbVBMetaImageHeader
*)slot_data
->vbmeta_images
[0].vbmeta_data
,
1503 /* Fill in |ab_suffix| field. */
1504 slot_data
->ab_suffix
= avb_strdup(ab_suffix
);
1505 if (slot_data
->ab_suffix
== NULL
) {
1506 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1510 /* If verification is disabled, we are done ... we specifically
1511 * don't want to add any androidboot.* options since verification
1514 if (toplevel_vbmeta
.flags
& AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
) {
1515 /* Since verification is disabled we didn't process any
1516 * descriptors and thus there's no cmdline... so set root= such
1517 * that the system partition is mounted.
1519 avb_assert(slot_data
->cmdline
== NULL
);
1520 // Devices with dynamic partitions won't have system partition.
1521 // Instead, it has a large super partition to accommodate *.img files.
1522 // See b/119551429 for details.
1523 if (has_system_partition(ops
, ab_suffix
)) {
1524 slot_data
->cmdline
=
1525 avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1527 // The |cmdline| field should be a NUL-terminated string.
1528 slot_data
->cmdline
= avb_strdup("");
1530 if (slot_data
->cmdline
== NULL
) {
1531 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1535 /* If requested, manage dm-verity mode... */
1536 AvbHashtreeErrorMode resolved_hashtree_error_mode
= hashtree_error_mode
;
1537 if (hashtree_error_mode
==
1538 AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
) {
1540 io_ret
= avb_manage_hashtree_error_mode(
1541 ops
, flags
, slot_data
, &resolved_hashtree_error_mode
);
1542 if (io_ret
!= AVB_IO_RESULT_OK
) {
1543 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_IO
;
1544 if (io_ret
== AVB_IO_RESULT_ERROR_OOM
) {
1545 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1550 slot_data
->resolved_hashtree_error_mode
= resolved_hashtree_error_mode
;
1552 /* Add options... */
1553 AvbSlotVerifyResult sub_ret
;
1554 sub_ret
= avb_append_options(ops
,
1559 hashtree_error_mode
,
1560 resolved_hashtree_error_mode
);
1561 if (sub_ret
!= AVB_SLOT_VERIFY_RESULT_OK
) {
1567 /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1568 if (slot_data
->cmdline
!= NULL
&& avb_strlen(slot_data
->cmdline
) != 0) {
1570 new_cmdline
= avb_sub_cmdline(ops
,
1573 using_boot_for_vbmeta
,
1574 additional_cmdline_subst
);
1575 if (new_cmdline
!= slot_data
->cmdline
) {
1576 if (new_cmdline
== NULL
) {
1577 ret
= AVB_SLOT_VERIFY_RESULT_ERROR_OOM
;
1580 avb_free(slot_data
->cmdline
);
1581 slot_data
->cmdline
= new_cmdline
;
1585 if (out_data
!= NULL
) {
1586 *out_data
= slot_data
;
1588 avb_slot_verify_data_free(slot_data
);
1591 avb_free_cmdline_subst_list(additional_cmdline_subst
);
1592 additional_cmdline_subst
= NULL
;
1594 if (!allow_verification_error
) {
1595 avb_assert(ret
== AVB_SLOT_VERIFY_RESULT_OK
);
1601 if (slot_data
!= NULL
) {
1602 avb_slot_verify_data_free(slot_data
);
1604 if (additional_cmdline_subst
!= NULL
) {
1605 avb_free_cmdline_subst_list(additional_cmdline_subst
);
1610 void avb_slot_verify_data_free(AvbSlotVerifyData
* data
) {
1611 if (data
->ab_suffix
!= NULL
) {
1612 avb_free(data
->ab_suffix
);
1614 if (data
->cmdline
!= NULL
) {
1615 avb_free(data
->cmdline
);
1617 if (data
->vbmeta_images
!= NULL
) {
1619 for (n
= 0; n
< data
->num_vbmeta_images
; n
++) {
1620 AvbVBMetaData
* vbmeta_image
= &data
->vbmeta_images
[n
];
1621 if (vbmeta_image
->partition_name
!= NULL
) {
1622 avb_free(vbmeta_image
->partition_name
);
1624 if (vbmeta_image
->vbmeta_data
!= NULL
) {
1625 avb_free(vbmeta_image
->vbmeta_data
);
1628 avb_free(data
->vbmeta_images
);
1630 if (data
->loaded_partitions
!= NULL
) {
1632 for (n
= 0; n
< data
->num_loaded_partitions
; n
++) {
1633 AvbPartitionData
* loaded_partition
= &data
->loaded_partitions
[n
];
1634 if (loaded_partition
->partition_name
!= NULL
) {
1635 avb_free(loaded_partition
->partition_name
);
1637 if (loaded_partition
->data
!= NULL
&& !loaded_partition
->preloaded
) {
1638 avb_free(loaded_partition
->data
);
1641 avb_free(data
->loaded_partitions
);
1646 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result
) {
1647 const char* ret
= NULL
;
1650 case AVB_SLOT_VERIFY_RESULT_OK
:
1653 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM
:
1656 case AVB_SLOT_VERIFY_RESULT_ERROR_IO
:
1659 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
:
1660 ret
= "ERROR_VERIFICATION";
1662 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
:
1663 ret
= "ERROR_ROLLBACK_INDEX";
1665 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
:
1666 ret
= "ERROR_PUBLIC_KEY_REJECTED";
1668 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
:
1669 ret
= "ERROR_INVALID_METADATA";
1671 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
:
1672 ret
= "ERROR_UNSUPPORTED_VERSION";
1674 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
:
1675 ret
= "ERROR_INVALID_ARGUMENT";
1677 /* Do not add a 'default:' case here because of -Wswitch. */
1681 avb_error("Unknown AvbSlotVerifyResult value.\n");
1688 void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData
* data
,
1689 AvbDigestType digest_type
,
1690 uint8_t* out_digest
) {
1694 switch (digest_type
) {
1695 case AVB_DIGEST_TYPE_SHA256
: {
1697 avb_sha256_init(&ctx
);
1698 for (n
= 0; n
< data
->num_vbmeta_images
; n
++) {
1699 avb_sha256_update(&ctx
,
1700 data
->vbmeta_images
[n
].vbmeta_data
,
1701 data
->vbmeta_images
[n
].vbmeta_size
);
1703 avb_memcpy(out_digest
, avb_sha256_final(&ctx
), AVB_SHA256_DIGEST_SIZE
);
1707 case AVB_DIGEST_TYPE_SHA512
: {
1709 avb_sha512_init(&ctx
);
1710 for (n
= 0; n
< data
->num_vbmeta_images
; n
++) {
1711 avb_sha512_update(&ctx
,
1712 data
->vbmeta_images
[n
].vbmeta_data
,
1713 data
->vbmeta_images
[n
].vbmeta_size
);
1715 avb_memcpy(out_digest
, avb_sha512_final(&ctx
), AVB_SHA512_DIGEST_SIZE
);
1719 /* Do not add a 'default:' case here because of -Wswitch. */
1723 avb_fatal("Unknown digest type");