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