efi_loader: definition of GetNextVariableName()
[oweals/u-boot.git] / lib / libavb / avb_slot_verify.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright (C) 2016 The Android Open Source Project
4  */
5
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"
13 #include "avb_sha.h"
14 #include "avb_util.h"
15 #include "avb_vbmeta_image.h"
16 #include "avb_version.h"
17 #include <malloc.h>
18
19 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
20 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
21
22 /* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
23 #define MAX_NUMBER_OF_VBMETA_IMAGES 32
24
25 /* Maximum size of a vbmeta image - 64 KiB. */
26 #define VBMETA_MAX_SIZE (64 * 1024)
27
28 static AvbSlotVerifyResult initialize_persistent_digest(
29     AvbOps* ops,
30     const char* part_name,
31     const char* persistent_value_name,
32     size_t digest_size,
33     const uint8_t* initial_digest,
34     uint8_t* out_digest);
35
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.
39  */
40 static inline bool result_should_continue(AvbSlotVerifyResult result) {
41   switch (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:
47       return false;
48
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:
53       return true;
54   }
55
56   return false;
57 }
58
59 static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
60                                                const char* part_name,
61                                                uint64_t image_size,
62                                                uint8_t** out_image_buf,
63                                                bool* out_image_preloaded) {
64   size_t part_num_read;
65   AvbIOResult io_ret;
66
67   /* Make sure that we do not overwrite existing data. */
68   avb_assert(*out_image_buf == NULL);
69   avb_assert(!*out_image_preloaded);
70
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;
76   }
77
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;
87     }
88
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;
93       }
94       *out_image_preloaded = true;
95     }
96   }
97
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;
103     }
104
105     io_ret = ops->read_from_partition(ops,
106                                       part_name,
107                                       0 /* offset */,
108                                       image_size,
109                                       *out_image_buf,
110                                       &part_num_read);
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;
116     }
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;
120     }
121   }
122
123   return AVB_SLOT_VERIFY_RESULT_OK;
124 }
125
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.
132  *
133  * Returns AVB_SLOT_VERIFY_RESULT_OK on success, otherwise returns an
134  * AVB_SLOT_VERIFY_RESULT_ERROR_* error code.
135  *
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.
141  */
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;
150
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;
154   }
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;
159   }
160
161   io_ret = ops->read_persistent_value(ops,
162                                       persistent_value_name,
163                                       expected_digest_size,
164                                       out_digest,
165                                       &stored_digest_size);
166
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,
174                                      part_name,
175                                      persistent_value_name,
176                                      expected_digest_size,
177                                      initial_digest,
178                                      out_digest);
179     avb_free(persistent_value_name);
180     return ret;
181   }
182   avb_free(persistent_value_name);
183
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) {
193     avb_errorv(
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) {
200     avb_errorv(
201         part_name, ": Persistent digest is not of expected size.\n", NULL);
202     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
203   }
204   return AVB_SLOT_VERIFY_RESULT_OK;
205 }
206
207 static AvbSlotVerifyResult initialize_persistent_digest(
208     AvbOps* ops,
209     const char* part_name,
210     const char* persistent_value_name,
211     size_t digest_size,
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;
217
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;
224   }
225
226   if (is_device_unlocked) {
227     avb_debugv(part_name,
228                ": Digest does not exist, device unlocked so not initializing "
229                "digest.\n",
230                NULL);
231     return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
232   }
233
234   // Device locked; initialize digest with given initial value.
235   avb_debugv(part_name,
236              ": Digest does not exist, initializing persistent digest.\n",
237              NULL);
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;
245   }
246
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",
255                NULL);
256   }
257   return ret;
258 }
259
260 static AvbSlotVerifyResult load_and_verify_hash_partition(
261     AvbOps* ops,
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;
273   AvbIOResult io_ret;
274   uint8_t* image_buf = NULL;
275   bool image_preloaded = false;
276   uint8_t* digest;
277   size_t digest_len;
278   const char* found;
279   uint64_t image_size;
280   size_t expected_digest_len = 0;
281   uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
282   const uint8_t* expected_digest = NULL;
283
284   if (!avb_hash_descriptor_validate_and_byteswap(
285           (const AvbHashDescriptor*)descriptor, &hash_desc)) {
286     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
287     goto out;
288   }
289
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;
294
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;
298     goto out;
299   }
300
301   /* Don't bother loading or validating unless the partition was
302    * requested in the first place.
303    */
304   found = avb_strv_find_str(requested_partitions,
305                             (const char*)desc_partition_name,
306                             hash_desc.partition_name_len);
307   if (found == NULL) {
308     ret = AVB_SLOT_VERIFY_RESULT_OK;
309     goto out;
310   }
311
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;
317       goto out;
318     }
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.
325      */
326     avb_error("Cannot use A/B with a persistent digest.\n");
327     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
328     goto out;
329   } else {
330     /* Add ab_suffix to the partition name. */
331     if (!avb_str_concat(part_name,
332                         sizeof part_name,
333                         (const char*)desc_partition_name,
334                         hash_desc.partition_name_len,
335                         ab_suffix,
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;
339       goto out;
340     }
341   }
342
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.
346    *
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.
350    */
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;
356       goto out;
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;
360       goto out;
361     }
362     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
363   }
364
365   ret = load_full_partition(
366       ops, part_name, image_size, &image_buf, &image_preloaded);
367   if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
368     goto out;
369   }
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
372   // used later.
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;
380   }
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;
393   } else {
394     avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
395     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
396     goto out;
397   }
398
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.
407      */
408     ret = read_persistent_digest(
409         ops, part_name, digest_len, digest, expected_digest_buf);
410     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
411       goto out;
412     }
413   } else {
414     /* Expect a match to the digest in the descriptor. */
415     expected_digest_len = hash_desc.digest_len;
416     expected_digest = desc_digest;
417   }
418
419   if (digest_len != expected_digest_len) {
420     avb_errorv(
421         part_name, ": Digest in descriptor not of expected size.\n", NULL);
422     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
423     goto out;
424   }
425
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",
429                NULL);
430     ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
431     goto out;
432   }
433
434   ret = AVB_SLOT_VERIFY_RESULT_OK;
435
436 out:
437
438   /* If it worked and something was loaded, copy to slot_data. */
439   if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
440       image_buf != NULL) {
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;
445       goto fail;
446     }
447     loaded_partition =
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;
453     image_buf = NULL;
454   }
455
456 fail:
457   if (image_buf != NULL && !image_preloaded) {
458     avb_free(image_buf);
459   }
460   return ret;
461 }
462
463 static AvbSlotVerifyResult load_requested_partitions(
464     AvbOps* ops,
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;
471   size_t n;
472
473   for (n = 0; requested_partitions[n] != NULL; n++) {
474     char part_name[AVB_PART_NAME_MAX_SIZE];
475     AvbIOResult io_ret;
476     uint64_t image_size;
477     AvbPartitionData* loaded_partition;
478
479     if (!avb_str_concat(part_name,
480                         sizeof part_name,
481                         requested_partitions[n],
482                         avb_strlen(requested_partitions[n]),
483                         ab_suffix,
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;
487       goto out;
488     }
489
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;
493       goto out;
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;
497       goto out;
498     }
499     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
500
501     ret = load_full_partition(
502         ops, part_name, image_size, &image_buf, &image_preloaded);
503     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
504       goto out;
505     }
506
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;
511       goto out;
512     }
513     loaded_partition =
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;
518       goto out;
519     }
520     loaded_partition->data_size = image_size;
521     loaded_partition->data = image_buf; /* Transferring the owner. */
522     loaded_partition->preloaded = image_preloaded;
523     image_buf = NULL;
524     image_preloaded = false;
525   }
526
527   ret = AVB_SLOT_VERIFY_RESULT_OK;
528
529 out:
530   /* Free the current buffer if any. */
531   if (image_buf != NULL && !image_preloaded) {
532     avb_free(image_buf);
533   }
534   /* Buffers that are already saved in slot_data will be handled by the caller
535    * even on failure. */
536   return ret;
537 }
538
539 static AvbSlotVerifyResult load_and_verify_vbmeta(
540     AvbOps* ops,
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;
556   AvbIOResult io_ret;
557   size_t vbmeta_offset;
558   size_t vbmeta_size;
559   uint8_t* vbmeta_buf = NULL;
560   size_t vbmeta_num_read;
561   AvbVBMetaVerifyResult vbmeta_ret;
562   const uint8_t* pk_data;
563   size_t pk_len;
564   AvbVBMetaImageHeader vbmeta_header;
565   uint64_t stored_rollback_index;
566   const AvbDescriptor** descriptors = NULL;
567   size_t num_descriptors;
568   size_t n;
569   bool is_main_vbmeta;
570   bool look_for_vbmeta_footer;
571   AvbVBMetaData* vbmeta_image_data = NULL;
572
573   ret = AVB_SLOT_VERIFY_RESULT_OK;
574
575   avb_assert(slot_data != NULL);
576
577   /* Since we allow top-level vbmeta in 'boot', use
578    * rollback_index_location to determine whether we're the main
579    * vbmeta struct.
580    */
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;
585     }
586   }
587
588   /* Don't use footers for vbmeta partitions ('vbmeta' or
589    * 'vbmeta_<partition_name>').
590    */
591   look_for_vbmeta_footer = true;
592   if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
593     look_for_vbmeta_footer = false;
594   }
595
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;
599     goto out;
600   }
601
602   /* Construct full partition name e.g. system_a. */
603   if (!avb_str_concat(full_partition_name,
604                       sizeof full_partition_name,
605                       partition_name,
606                       partition_name_len,
607                       ab_suffix,
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;
611     goto out;
612   }
613
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
618    * rationale).
619    */
620   vbmeta_offset = 0;
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;
625     AvbFooter footer;
626
627     io_ret = ops->read_from_partition(ops,
628                                       full_partition_name,
629                                       -AVB_FOOTER_SIZE,
630                                       AVB_FOOTER_SIZE,
631                                       footer_buf,
632                                       &footer_num_read);
633     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
634       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
635       goto out;
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;
639       goto out;
640     }
641     avb_assert(footer_num_read == AVB_FOOTER_SIZE);
642
643     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
644                                           &footer)) {
645       avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
646     } else {
647       /* Basic footer sanity check since the data is untrusted. */
648       if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
649         avb_errorv(
650             full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
651       } else {
652         vbmeta_offset = footer.vbmeta_offset;
653         vbmeta_size = footer.vbmeta_size;
654       }
655     }
656   }
657
658   vbmeta_buf = avb_malloc(vbmeta_size);
659   if (vbmeta_buf == NULL) {
660     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
661     goto out;
662   }
663
664   if (vbmeta_offset != 0) {
665     avb_debugv("Loading vbmeta struct in footer from partition '",
666                full_partition_name,
667                "'.\n",
668                NULL);
669   } else {
670     avb_debugv("Loading vbmeta struct from partition '",
671                full_partition_name,
672                "'.\n",
673                NULL);
674   }
675
676   io_ret = ops->read_from_partition(ops,
677                                     full_partition_name,
678                                     vbmeta_offset,
679                                     vbmeta_size,
680                                     vbmeta_buf,
681                                     &vbmeta_num_read);
682   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
683     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
684     goto out;
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.
688      */
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",
693                  NULL);
694       ret = load_and_verify_vbmeta(ops,
695                                    requested_partitions,
696                                    ab_suffix,
697                                    flags,
698                                    allow_verification_error,
699                                    0 /* toplevel_vbmeta_flags */,
700                                    0 /* rollback_index_location */,
701                                    "boot",
702                                    avb_strlen("boot"),
703                                    NULL /* expected_public_key */,
704                                    0 /* expected_public_key_length */,
705                                    slot_data,
706                                    out_algorithm_type,
707                                    out_additional_cmdline_subst);
708       goto out;
709     } else {
710       avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
711       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
712       goto out;
713     }
714   }
715   avb_assert(vbmeta_num_read <= vbmeta_size);
716
717   /* Check if the image is properly signed and get the public key used
718    * to sign the image.
719    */
720   vbmeta_ret =
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);
725       break;
726
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),
734                  "\n",
735                  NULL);
736       if (!allow_verification_error) {
737         goto out;
738       }
739       break;
740
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",
746                  NULL);
747       goto out;
748
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",
754                  NULL);
755       goto out;
756   }
757
758   /* Byteswap the header. */
759   avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
760                                              &vbmeta_header);
761
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;
765   } else {
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",
770                  NULL);
771       goto out;
772     }
773   }
774
775   uint32_t rollback_index_location_to_use = rollback_index_location;
776
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",
786                    NULL);
787         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
788         if (!allow_verification_error) {
789           goto out;
790         }
791       }
792     } else {
793       bool key_is_trusted = false;
794       const uint8_t* pk_metadata = NULL;
795       size_t pk_metadata_len = 0;
796
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;
802       }
803
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(
807             ops,
808             full_partition_name,
809             pk_data,
810             pk_len,
811             pk_metadata,
812             pk_metadata_len,
813             &key_is_trusted,
814             &rollback_index_location_to_use);
815       } else {
816         avb_assert(is_main_vbmeta);
817         io_ret = ops->validate_vbmeta_public_key(ops,
818                                                  pk_data,
819                                                  pk_len,
820                                                  pk_metadata,
821                                                  pk_metadata_len,
822                                                  &key_is_trusted);
823       }
824
825       if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
826         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
827         goto out;
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",
831                    NULL);
832         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
833         goto out;
834       }
835       if (!key_is_trusted) {
836         avb_errorv(full_partition_name,
837                    ": Public key used to sign data rejected.\n",
838                    NULL);
839         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
840         if (!allow_verification_error) {
841           goto out;
842         }
843       }
844     }
845   }
846
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;
852     goto out;
853   } else if (io_ret != AVB_IO_RESULT_OK) {
854     avb_errorv(full_partition_name,
855                ": Error getting rollback index for location.\n",
856                NULL);
857     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
858     goto out;
859   }
860   if (vbmeta_header.rollback_index < stored_rollback_index) {
861     avb_errorv(
862         full_partition_name,
863         ": Image rollback index is less than the stored rollback index.\n",
864         NULL);
865     ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
866     if (!allow_verification_error) {
867       goto out;
868     }
869   }
870
871   /* Copy vbmeta to vbmeta_images before recursing. */
872   if (is_main_vbmeta) {
873     avb_assert(slot_data->num_vbmeta_images == 0);
874   } else {
875     if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
876       avb_assert(slot_data->num_vbmeta_images > 0);
877     }
878   }
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;
882     goto out;
883   }
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.
891    */
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;
897
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.
901    */
902   if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
903     AvbSlotVerifyResult sub_ret;
904     avb_debugv(
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.
910      */
911     sub_ret = load_requested_partitions(
912         ops, requested_partitions, ab_suffix, slot_data);
913     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
914       ret = sub_ret;
915     }
916     goto out;
917   }
918
919   /* Now go through all descriptors and take the appropriate action:
920    *
921    * - hash descriptor: Load data from partition, calculate hash, and
922    *   checks that it matches what's in the hash descriptor.
923    *
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).
927    *
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).
931    */
932   descriptors =
933       avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
934   for (n = 0; n < num_descriptors; n++) {
935     AvbDescriptor desc;
936
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;
940       goto out;
941     }
942
943     switch (desc.tag) {
944       case AVB_DESCRIPTOR_TAG_HASH: {
945         AvbSlotVerifyResult sub_ret;
946         sub_ret = load_and_verify_hash_partition(ops,
947                                                  requested_partitions,
948                                                  ab_suffix,
949                                                  allow_verification_error,
950                                                  descriptors[n],
951                                                  slot_data);
952         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
953           ret = sub_ret;
954           if (!allow_verification_error || !result_should_continue(ret)) {
955             goto out;
956           }
957         }
958       } break;
959
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;
965
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",
970                      NULL);
971           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
972           goto out;
973         }
974
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",
979                      NULL);
980           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
981           goto out;
982         }
983
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",
988                      NULL);
989           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
990           goto out;
991         }
992
993         chain_partition_name = ((const uint8_t*)descriptors[n]) +
994                                sizeof(AvbChainPartitionDescriptor);
995         chain_public_key = chain_partition_name + chain_desc.partition_name_len;
996
997         sub_ret =
998             load_and_verify_vbmeta(ops,
999                                    requested_partitions,
1000                                    ab_suffix,
1001                                    flags,
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,
1007                                    chain_public_key,
1008                                    chain_desc.public_key_len,
1009                                    slot_data,
1010                                    NULL, /* out_algorithm_type */
1011                                    NULL /* out_additional_cmdline_subst */);
1012         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1013           ret = sub_ret;
1014           if (!result_should_continue(ret)) {
1015             goto out;
1016           }
1017         }
1018       } break;
1019
1020       case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
1021         const uint8_t* kernel_cmdline;
1022         AvbKernelCmdlineDescriptor kernel_cmdline_desc;
1023         bool apply_cmdline;
1024
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",
1030                      NULL);
1031           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1032           goto out;
1033         }
1034
1035         kernel_cmdline = ((const uint8_t*)descriptors[n]) +
1036                          sizeof(AvbKernelCmdlineDescriptor);
1037
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",
1042                      NULL);
1043           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1044           goto out;
1045         }
1046
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.
1051          */
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;
1057           }
1058         } else {
1059           if (kernel_cmdline_desc.flags &
1060               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
1061             apply_cmdline = false;
1062           }
1063         }
1064
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;
1071               goto out;
1072             }
1073             avb_memcpy(slot_data->cmdline,
1074                        kernel_cmdline,
1075                        kernel_cmdline_desc.kernel_cmdline_length);
1076           } else {
1077             /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
1078             size_t orig_size = avb_strlen(slot_data->cmdline);
1079             size_t new_size =
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;
1084               goto out;
1085             }
1086             avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
1087             new_cmdline[orig_size] = ' ';
1088             avb_memcpy(new_cmdline + orig_size + 1,
1089                        kernel_cmdline,
1090                        kernel_cmdline_desc.kernel_cmdline_length);
1091             avb_free(slot_data->cmdline);
1092             slot_data->cmdline = new_cmdline;
1093           }
1094         }
1095       } break;
1096
1097       case AVB_DESCRIPTOR_TAG_HASHTREE: {
1098         AvbHashtreeDescriptor hashtree_desc;
1099
1100         if (!avb_hashtree_descriptor_validate_and_byteswap(
1101                 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
1102           avb_errorv(
1103               full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
1104           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1105           goto out;
1106         }
1107
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.
1111          */
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);
1118
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;
1123             goto out;
1124           }
1125
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.
1129            */
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;
1135             goto out;
1136           }
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;
1140             goto out;
1141           }
1142           avb_memcpy(
1143               part_name, desc_partition_name, hashtree_desc.partition_name_len);
1144           part_name[hashtree_desc.partition_name_len] = '\0';
1145
1146           /* Determine the expected digest size from the hash algorithm. */
1147           if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1148               0) {
1149             digest_len = AVB_SHA1_DIGEST_SIZE;
1150           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1151                                 "sha256") == 0) {
1152             digest_len = AVB_SHA256_DIGEST_SIZE;
1153           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1154                                 "sha512") == 0) {
1155             digest_len = AVB_SHA512_DIGEST_SIZE;
1156           } else {
1157             avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1158             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1159             goto out;
1160           }
1161
1162           ret = read_persistent_digest(ops,
1163                                        part_name,
1164                                        digest_len,
1165                                        NULL /* initial_digest */,
1166                                        digest_buf);
1167           if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1168             goto out;
1169           }
1170
1171           if (out_additional_cmdline_subst) {
1172             ret =
1173                 avb_add_root_digest_substitution(part_name,
1174                                                  digest_buf,
1175                                                  digest_len,
1176                                                  out_additional_cmdline_subst);
1177             if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1178               goto out;
1179             }
1180           }
1181         }
1182       } break;
1183
1184       case AVB_DESCRIPTOR_TAG_PROPERTY:
1185         /* Do nothing. */
1186         break;
1187     }
1188   }
1189
1190   if (rollback_index_location < 0 ||
1191       rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1192     avb_errorv(
1193         full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1194     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1195     goto out;
1196   }
1197
1198   slot_data->rollback_indexes[rollback_index_location] =
1199       vbmeta_header.rollback_index;
1200
1201   if (out_algorithm_type != NULL) {
1202     *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1203   }
1204
1205 out:
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.
1208    */
1209   if (vbmeta_image_data == NULL) {
1210     if (vbmeta_buf != NULL) {
1211       avb_free(vbmeta_buf);
1212     }
1213   }
1214   if (descriptors != NULL) {
1215     avb_free(descriptors);
1216   }
1217   return ret;
1218 }
1219
1220 static AvbIOResult avb_manage_hashtree_error_mode(
1221     AvbOps* ops,
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;
1230
1231   avb_assert(out_hashtree_error_mode != NULL);
1232   avb_assert(ops->read_persistent_value != NULL);
1233   avb_assert(ops->write_persistent_value != NULL);
1234
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) {
1238     avb_debug(
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");
1249       goto out;
1250     }
1251     ret = AVB_HASHTREE_ERROR_MODE_EIO;
1252     io_ret = AVB_IO_RESULT_OK;
1253     goto out;
1254   }
1255
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,
1261                                       &num_bytes_read);
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;
1268     goto out;
1269   } else if (io_ret != AVB_IO_RESULT_OK) {
1270     avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1271     goto out;
1272   }
1273   if (num_bytes_read != AVB_SHA256_DIGEST_SIZE) {
1274     avb_error(
1275         "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
1276         ".\n");
1277     io_ret = AVB_IO_RESULT_ERROR_IO;
1278     goto out;
1279   }
1280
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;
1293   } else {
1294     // It did change!
1295     avb_debug(
1296         "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
1297     io_ret =
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");
1304       goto out;
1305     }
1306     ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1307     io_ret = AVB_IO_RESULT_OK;
1308   }
1309
1310 out:
1311   *out_hashtree_error_mode = ret;
1312   return io_ret;
1313 }
1314
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";
1318   char guid_buf[37];
1319   AvbIOResult io_ret;
1320
1321   if (!avb_str_concat(part_name,
1322                       sizeof part_name,
1323                       system_part_name,
1324                       avb_strlen(system_part_name),
1325                       ab_suffix,
1326                       avb_strlen(ab_suffix))) {
1327     avb_error("System partition name and suffix does not fit.\n");
1328     return false;
1329   }
1330
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");
1335     return false;
1336   } else if (io_ret != AVB_IO_RESULT_OK) {
1337     avb_error("Error getting unique GUID for system partition.\n");
1338     return false;
1339   }
1340
1341   return true;
1342 }
1343
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;
1358
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);
1365
1366   if (out_data != NULL) {
1367     *out_data = NULL;
1368   }
1369
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).
1373    */
1374   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1375       !allow_verification_error) {
1376     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1377     goto fail;
1378   }
1379
1380   /* Make sure passed-in AvbOps support persistent values if
1381    * asking for libavb to manage verity state.
1382    */
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) {
1386       avb_error(
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;
1391       goto fail;
1392     }
1393   }
1394
1395   /* Make sure passed-in AvbOps support verifying public keys and getting
1396    * rollback index location if not using a vbmeta partition.
1397    */
1398   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1399     if (ops->validate_public_key_for_partition == NULL) {
1400       avb_error(
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;
1404       goto fail;
1405     }
1406   } else {
1407     avb_assert(ops->validate_vbmeta_public_key != NULL);
1408   }
1409
1410   slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1411   if (slot_data == NULL) {
1412     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1413     goto fail;
1414   }
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;
1419     goto fail;
1420   }
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;
1425     goto fail;
1426   }
1427
1428   additional_cmdline_subst = avb_new_cmdline_subst_list();
1429   if (additional_cmdline_subst == NULL) {
1430     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1431     goto fail;
1432   }
1433
1434   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1435     if (requested_partitions == NULL || requested_partitions[0] == NULL) {
1436       avb_fatal(
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;
1440       goto fail;
1441     }
1442
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,
1447                                    ab_suffix,
1448                                    flags,
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 */,
1456                                    slot_data,
1457                                    &algorithm_type,
1458                                    additional_cmdline_subst);
1459       if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1460         goto fail;
1461       }
1462     }
1463
1464   } else {
1465     /* Usual path, load "vbmeta"... */
1466     ret = load_and_verify_vbmeta(ops,
1467                                  requested_partitions,
1468                                  ab_suffix,
1469                                  flags,
1470                                  allow_verification_error,
1471                                  0 /* toplevel_vbmeta_flags */,
1472                                  0 /* rollback_index_location */,
1473                                  "vbmeta",
1474                                  avb_strlen("vbmeta"),
1475                                  NULL /* expected_public_key */,
1476                                  0 /* expected_public_key_length */,
1477                                  slot_data,
1478                                  &algorithm_type,
1479                                  additional_cmdline_subst);
1480     if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1481       goto fail;
1482     }
1483   }
1484
1485   if (!result_should_continue(ret)) {
1486     goto fail;
1487   }
1488
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) {
1492       avb_assert(
1493           avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1494       using_boot_for_vbmeta = true;
1495     }
1496   }
1497
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,
1501       &toplevel_vbmeta);
1502
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;
1507     goto fail;
1508   }
1509
1510   /* If verification is disabled, we are done ... we specifically
1511    * don't want to add any androidboot.* options since verification
1512    * is disabled.
1513    */
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.
1518      */
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)");
1526     } else {
1527       // The |cmdline| field should be a NUL-terminated string.
1528       slot_data->cmdline = avb_strdup("");
1529     }
1530     if (slot_data->cmdline == NULL) {
1531       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1532       goto fail;
1533     }
1534   } else {
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) {
1539       AvbIOResult io_ret;
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;
1546         }
1547         goto fail;
1548       }
1549     }
1550     slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
1551
1552     /* Add options... */
1553     AvbSlotVerifyResult sub_ret;
1554     sub_ret = avb_append_options(ops,
1555                                  flags,
1556                                  slot_data,
1557                                  &toplevel_vbmeta,
1558                                  algorithm_type,
1559                                  hashtree_error_mode,
1560                                  resolved_hashtree_error_mode);
1561     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1562       ret = sub_ret;
1563       goto fail;
1564     }
1565   }
1566
1567   /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1568   if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
1569     char* new_cmdline;
1570     new_cmdline = avb_sub_cmdline(ops,
1571                                   slot_data->cmdline,
1572                                   ab_suffix,
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;
1578         goto fail;
1579       }
1580       avb_free(slot_data->cmdline);
1581       slot_data->cmdline = new_cmdline;
1582     }
1583   }
1584
1585   if (out_data != NULL) {
1586     *out_data = slot_data;
1587   } else {
1588     avb_slot_verify_data_free(slot_data);
1589   }
1590
1591   avb_free_cmdline_subst_list(additional_cmdline_subst);
1592   additional_cmdline_subst = NULL;
1593
1594   if (!allow_verification_error) {
1595     avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1596   }
1597
1598   return ret;
1599
1600 fail:
1601   if (slot_data != NULL) {
1602     avb_slot_verify_data_free(slot_data);
1603   }
1604   if (additional_cmdline_subst != NULL) {
1605     avb_free_cmdline_subst_list(additional_cmdline_subst);
1606   }
1607   return ret;
1608 }
1609
1610 void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1611   if (data->ab_suffix != NULL) {
1612     avb_free(data->ab_suffix);
1613   }
1614   if (data->cmdline != NULL) {
1615     avb_free(data->cmdline);
1616   }
1617   if (data->vbmeta_images != NULL) {
1618     size_t n;
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);
1623       }
1624       if (vbmeta_image->vbmeta_data != NULL) {
1625         avb_free(vbmeta_image->vbmeta_data);
1626       }
1627     }
1628     avb_free(data->vbmeta_images);
1629   }
1630   if (data->loaded_partitions != NULL) {
1631     size_t n;
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);
1636       }
1637       if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1638         avb_free(loaded_partition->data);
1639       }
1640     }
1641     avb_free(data->loaded_partitions);
1642   }
1643   avb_free(data);
1644 }
1645
1646 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1647   const char* ret = NULL;
1648
1649   switch (result) {
1650     case AVB_SLOT_VERIFY_RESULT_OK:
1651       ret = "OK";
1652       break;
1653     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1654       ret = "ERROR_OOM";
1655       break;
1656     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1657       ret = "ERROR_IO";
1658       break;
1659     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1660       ret = "ERROR_VERIFICATION";
1661       break;
1662     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1663       ret = "ERROR_ROLLBACK_INDEX";
1664       break;
1665     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1666       ret = "ERROR_PUBLIC_KEY_REJECTED";
1667       break;
1668     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1669       ret = "ERROR_INVALID_METADATA";
1670       break;
1671     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1672       ret = "ERROR_UNSUPPORTED_VERSION";
1673       break;
1674     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1675       ret = "ERROR_INVALID_ARGUMENT";
1676       break;
1677       /* Do not add a 'default:' case here because of -Wswitch. */
1678   }
1679
1680   if (ret == NULL) {
1681     avb_error("Unknown AvbSlotVerifyResult value.\n");
1682     ret = "(unknown)";
1683   }
1684
1685   return ret;
1686 }
1687
1688 void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
1689                                                   AvbDigestType digest_type,
1690                                                   uint8_t* out_digest) {
1691   bool ret = false;
1692   size_t n;
1693
1694   switch (digest_type) {
1695     case AVB_DIGEST_TYPE_SHA256: {
1696       AvbSHA256Ctx ctx;
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);
1702       }
1703       avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
1704       ret = true;
1705     } break;
1706
1707     case AVB_DIGEST_TYPE_SHA512: {
1708       AvbSHA512Ctx ctx;
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);
1714       }
1715       avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
1716       ret = true;
1717     } break;
1718
1719       /* Do not add a 'default:' case here because of -Wswitch. */
1720   }
1721
1722   if (!ret) {
1723     avb_fatal("Unknown digest type");
1724   }
1725 }