mx6ul_14x14_evk: Avoid overlap of environment over U-Boot proper
[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 <log.h>
18 #include <malloc.h>
19
20 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
21 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
22
23 /* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
24 #define MAX_NUMBER_OF_VBMETA_IMAGES 32
25
26 /* Maximum size of a vbmeta image - 64 KiB. */
27 #define VBMETA_MAX_SIZE (64 * 1024)
28
29 static AvbSlotVerifyResult initialize_persistent_digest(
30     AvbOps* ops,
31     const char* part_name,
32     const char* persistent_value_name,
33     size_t digest_size,
34     const uint8_t* initial_digest,
35     uint8_t* out_digest);
36
37 /* Helper function to see if we should continue with verification in
38  * allow_verification_error=true mode if something goes wrong. See the
39  * comments for the avb_slot_verify() function for more information.
40  */
41 static inline bool result_should_continue(AvbSlotVerifyResult result) {
42   switch (result) {
43     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
44     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
45     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
46     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
47     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
48       return false;
49
50     case AVB_SLOT_VERIFY_RESULT_OK:
51     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
52     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
53     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
54       return true;
55   }
56
57   return false;
58 }
59
60 static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
61                                                const char* part_name,
62                                                uint64_t image_size,
63                                                uint8_t** out_image_buf,
64                                                bool* out_image_preloaded) {
65   size_t part_num_read;
66   AvbIOResult io_ret;
67
68   /* Make sure that we do not overwrite existing data. */
69   avb_assert(*out_image_buf == NULL);
70   avb_assert(!*out_image_preloaded);
71
72   /* We are going to implicitly cast image_size from uint64_t to size_t in the
73    * following code, so we need to make sure that the cast is safe. */
74   if (image_size != (size_t)(image_size)) {
75     avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
76     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
77   }
78
79   /* Try use a preloaded one. */
80   if (ops->get_preloaded_partition != NULL) {
81     io_ret = ops->get_preloaded_partition(
82         ops, part_name, image_size, out_image_buf, &part_num_read);
83     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
84       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
85     } else if (io_ret != AVB_IO_RESULT_OK) {
86       avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
87       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
88     }
89
90     if (*out_image_buf != NULL) {
91       if (part_num_read != image_size) {
92         avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
93         return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
94       }
95       *out_image_preloaded = true;
96     }
97   }
98
99   /* Allocate and copy the partition. */
100   if (!*out_image_preloaded) {
101     *out_image_buf = avb_malloc(image_size);
102     if (*out_image_buf == NULL) {
103       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
104     }
105
106     io_ret = ops->read_from_partition(ops,
107                                       part_name,
108                                       0 /* offset */,
109                                       image_size,
110                                       *out_image_buf,
111                                       &part_num_read);
112     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
113       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
114     } else if (io_ret != AVB_IO_RESULT_OK) {
115       avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
116       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
117     }
118     if (part_num_read != image_size) {
119       avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
120       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
121     }
122   }
123
124   return AVB_SLOT_VERIFY_RESULT_OK;
125 }
126
127 /* Reads a persistent digest stored as a named persistent value corresponding to
128  * the given |part_name|. The value is returned in |out_digest| which must point
129  * to |expected_digest_size| bytes. If there is no digest stored for |part_name|
130  * it can be initialized by providing a non-NULL |initial_digest| of length
131  * |expected_digest_size|. This automatic initialization will only occur if the
132  * device is currently locked. The |initial_digest| may be NULL.
133  *
134  * Returns AVB_SLOT_VERIFY_RESULT_OK on success, otherwise returns an
135  * AVB_SLOT_VERIFY_RESULT_ERROR_* error code.
136  *
137  * If the value does not exist, is not supported, or is not populated, and
138  * |initial_digest| is NULL, returns
139  * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA. If |expected_digest_size| does
140  * not match the stored digest size, also returns
141  * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA.
142  */
143 static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
144                                                   const char* part_name,
145                                                   size_t expected_digest_size,
146                                                   const uint8_t* initial_digest,
147                                                   uint8_t* out_digest) {
148   char* persistent_value_name = NULL;
149   AvbIOResult io_ret = AVB_IO_RESULT_OK;
150   size_t stored_digest_size = 0;
151
152   if (ops->read_persistent_value == NULL) {
153     avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
154     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
155   }
156   persistent_value_name =
157       avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
158   if (persistent_value_name == NULL) {
159     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
160   }
161
162   io_ret = ops->read_persistent_value(ops,
163                                       persistent_value_name,
164                                       expected_digest_size,
165                                       out_digest,
166                                       &stored_digest_size);
167
168   // If no such named persistent value exists and an initial digest value was
169   // given, initialize the named persistent value with the given digest. If
170   // initialized successfully, this will recurse into this function but with a
171   // NULL initial_digest.
172   if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE && initial_digest) {
173     AvbSlotVerifyResult ret =
174         initialize_persistent_digest(ops,
175                                      part_name,
176                                      persistent_value_name,
177                                      expected_digest_size,
178                                      initial_digest,
179                                      out_digest);
180     avb_free(persistent_value_name);
181     return ret;
182   }
183   avb_free(persistent_value_name);
184
185   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
186     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
187   } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
188     // Treat a missing persistent value as a verification error, which is
189     // ignoreable, rather than a metadata error which is not.
190     avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
191     return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
192   } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
193              io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE) {
194     avb_errorv(
195         part_name, ": Persistent digest is not of expected size.\n", NULL);
196     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
197   } else if (io_ret != AVB_IO_RESULT_OK) {
198     avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
199     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
200   } else if (expected_digest_size != stored_digest_size) {
201     avb_errorv(
202         part_name, ": Persistent digest is not of expected size.\n", NULL);
203     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
204   }
205   return AVB_SLOT_VERIFY_RESULT_OK;
206 }
207
208 static AvbSlotVerifyResult initialize_persistent_digest(
209     AvbOps* ops,
210     const char* part_name,
211     const char* persistent_value_name,
212     size_t digest_size,
213     const uint8_t* initial_digest,
214     uint8_t* out_digest) {
215   AvbSlotVerifyResult ret;
216   AvbIOResult io_ret = AVB_IO_RESULT_OK;
217   bool is_device_unlocked = true;
218
219   io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
220   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
221     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
222   } else if (io_ret != AVB_IO_RESULT_OK) {
223     avb_error("Error getting device lock state.\n");
224     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
225   }
226
227   if (is_device_unlocked) {
228     avb_debugv(part_name,
229                ": Digest does not exist, device unlocked so not initializing "
230                "digest.\n",
231                NULL);
232     return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
233   }
234
235   // Device locked; initialize digest with given initial value.
236   avb_debugv(part_name,
237              ": Digest does not exist, initializing persistent digest.\n",
238              NULL);
239   io_ret = ops->write_persistent_value(
240       ops, persistent_value_name, digest_size, initial_digest);
241   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
242     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
243   } else if (io_ret != AVB_IO_RESULT_OK) {
244     avb_errorv(part_name, ": Error initializing persistent digest.\n", NULL);
245     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
246   }
247
248   // To ensure that the digest value was written successfully - and avoid a
249   // scenario where the digest is simply 'initialized' on every verify - recurse
250   // into read_persistent_digest to read back the written value. The NULL
251   // initial_digest ensures that this will not recurse again.
252   ret = read_persistent_digest(ops, part_name, digest_size, NULL, out_digest);
253   if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
254     avb_errorv(part_name,
255                ": Reading back initialized persistent digest failed!\n",
256                NULL);
257   }
258   return ret;
259 }
260
261 static AvbSlotVerifyResult load_and_verify_hash_partition(
262     AvbOps* ops,
263     const char* const* requested_partitions,
264     const char* ab_suffix,
265     bool allow_verification_error,
266     const AvbDescriptor* descriptor,
267     AvbSlotVerifyData* slot_data) {
268   AvbHashDescriptor hash_desc;
269   const uint8_t* desc_partition_name = NULL;
270   const uint8_t* desc_salt;
271   const uint8_t* desc_digest;
272   char part_name[AVB_PART_NAME_MAX_SIZE];
273   AvbSlotVerifyResult ret;
274   AvbIOResult io_ret;
275   uint8_t* image_buf = NULL;
276   bool image_preloaded = false;
277   uint8_t* digest;
278   size_t digest_len;
279   const char* found;
280   uint64_t image_size;
281   size_t expected_digest_len = 0;
282   uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
283   const uint8_t* expected_digest = NULL;
284
285   if (!avb_hash_descriptor_validate_and_byteswap(
286           (const AvbHashDescriptor*)descriptor, &hash_desc)) {
287     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
288     goto out;
289   }
290
291   desc_partition_name =
292       ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
293   desc_salt = desc_partition_name + hash_desc.partition_name_len;
294   desc_digest = desc_salt + hash_desc.salt_len;
295
296   if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
297     avb_error("Partition name is not valid UTF-8.\n");
298     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
299     goto out;
300   }
301
302   /* Don't bother loading or validating unless the partition was
303    * requested in the first place.
304    */
305   found = avb_strv_find_str(requested_partitions,
306                             (const char*)desc_partition_name,
307                             hash_desc.partition_name_len);
308   if (found == NULL) {
309     ret = AVB_SLOT_VERIFY_RESULT_OK;
310     goto out;
311   }
312
313   if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
314     /* No ab_suffix, just copy the partition name as is. */
315     if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
316       avb_error("Partition name does not fit.\n");
317       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
318       goto out;
319     }
320     avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
321     part_name[hash_desc.partition_name_len] = '\0';
322   } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
323     /* No ab_suffix allowed for partitions without a digest in the descriptor
324      * because these partitions hold data unique to this device and are not
325      * updated using an A/B scheme.
326      */
327     avb_error("Cannot use A/B with a persistent digest.\n");
328     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
329     goto out;
330   } else {
331     /* Add ab_suffix to the partition name. */
332     if (!avb_str_concat(part_name,
333                         sizeof part_name,
334                         (const char*)desc_partition_name,
335                         hash_desc.partition_name_len,
336                         ab_suffix,
337                         avb_strlen(ab_suffix))) {
338       avb_error("Partition name and suffix does not fit.\n");
339       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
340       goto out;
341     }
342   }
343
344   /* If we're allowing verification errors then hash_desc.image_size
345    * may no longer match what's in the partition... so in this case
346    * just load the entire partition.
347    *
348    * For example, this can happen if a developer does 'fastboot flash
349    * boot /path/to/new/and/bigger/boot.img'. We want this to work
350    * since it's such a common workflow.
351    */
352   image_size = hash_desc.image_size;
353   if (allow_verification_error) {
354     io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
355     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
356       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
357       goto out;
358     } else if (io_ret != AVB_IO_RESULT_OK) {
359       avb_errorv(part_name, ": Error determining partition size.\n", NULL);
360       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
361       goto out;
362     }
363     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
364   }
365
366   ret = load_full_partition(
367       ops, part_name, image_size, &image_buf, &image_preloaded);
368   if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
369     goto out;
370   }
371   // Although only one of the type might be used, we have to defined the
372   // structure here so that they would live outside the 'if/else' scope to be
373   // used later.
374   AvbSHA256Ctx sha256_ctx;
375   AvbSHA512Ctx sha512_ctx;
376   size_t image_size_to_hash = hash_desc.image_size;
377   // If we allow verification error and the whole partition is smaller than
378   // image size in hash descriptor, we just hash the whole partition.
379   if (image_size_to_hash > image_size) {
380     image_size_to_hash = image_size;
381   }
382   if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
383     avb_sha256_init(&sha256_ctx);
384     avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
385     avb_sha256_update(&sha256_ctx, image_buf, image_size_to_hash);
386     digest = avb_sha256_final(&sha256_ctx);
387     digest_len = AVB_SHA256_DIGEST_SIZE;
388   } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
389     avb_sha512_init(&sha512_ctx);
390     avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
391     avb_sha512_update(&sha512_ctx, image_buf, image_size_to_hash);
392     digest = avb_sha512_final(&sha512_ctx);
393     digest_len = AVB_SHA512_DIGEST_SIZE;
394   } else {
395     avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
396     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
397     goto out;
398   }
399
400   if (hash_desc.digest_len == 0) {
401     /* Expect a match to a persistent digest. */
402     avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
403     expected_digest_len = digest_len;
404     expected_digest = expected_digest_buf;
405     avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
406     /* Pass |digest| as the |initial_digest| so devices not yet initialized get
407      * initialized to the current partition digest.
408      */
409     ret = read_persistent_digest(
410         ops, part_name, digest_len, digest, expected_digest_buf);
411     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
412       goto out;
413     }
414   } else {
415     /* Expect a match to the digest in the descriptor. */
416     expected_digest_len = hash_desc.digest_len;
417     expected_digest = desc_digest;
418   }
419
420   if (digest_len != expected_digest_len) {
421     avb_errorv(
422         part_name, ": Digest in descriptor not of expected size.\n", NULL);
423     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
424     goto out;
425   }
426
427   if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
428     avb_errorv(part_name,
429                ": Hash of data does not match digest in descriptor.\n",
430                NULL);
431     ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
432     goto out;
433   }
434
435   ret = AVB_SLOT_VERIFY_RESULT_OK;
436
437 out:
438
439   /* If it worked and something was loaded, copy to slot_data. */
440   if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
441       image_buf != NULL) {
442     AvbPartitionData* loaded_partition;
443     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
444       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
445       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
446       goto fail;
447     }
448     loaded_partition =
449         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
450     loaded_partition->partition_name = avb_strdup(found);
451     loaded_partition->data_size = image_size;
452     loaded_partition->data = image_buf;
453     loaded_partition->preloaded = image_preloaded;
454     image_buf = NULL;
455   }
456
457 fail:
458   if (image_buf != NULL && !image_preloaded) {
459     avb_free(image_buf);
460   }
461   return ret;
462 }
463
464 static AvbSlotVerifyResult load_requested_partitions(
465     AvbOps* ops,
466     const char* const* requested_partitions,
467     const char* ab_suffix,
468     AvbSlotVerifyData* slot_data) {
469   AvbSlotVerifyResult ret;
470   uint8_t* image_buf = NULL;
471   bool image_preloaded = false;
472   size_t n;
473
474   for (n = 0; requested_partitions[n] != NULL; n++) {
475     char part_name[AVB_PART_NAME_MAX_SIZE];
476     AvbIOResult io_ret;
477     uint64_t image_size;
478     AvbPartitionData* loaded_partition;
479
480     if (!avb_str_concat(part_name,
481                         sizeof part_name,
482                         requested_partitions[n],
483                         avb_strlen(requested_partitions[n]),
484                         ab_suffix,
485                         avb_strlen(ab_suffix))) {
486       avb_error("Partition name and suffix does not fit.\n");
487       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
488       goto out;
489     }
490
491     io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
492     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
493       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
494       goto out;
495     } else if (io_ret != AVB_IO_RESULT_OK) {
496       avb_errorv(part_name, ": Error determining partition size.\n", NULL);
497       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
498       goto out;
499     }
500     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
501
502     ret = load_full_partition(
503         ops, part_name, image_size, &image_buf, &image_preloaded);
504     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
505       goto out;
506     }
507
508     /* Move to slot_data. */
509     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
510       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
511       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
512       goto out;
513     }
514     loaded_partition =
515         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
516     loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
517     if (loaded_partition->partition_name == NULL) {
518       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
519       goto out;
520     }
521     loaded_partition->data_size = image_size;
522     loaded_partition->data = image_buf; /* Transferring the owner. */
523     loaded_partition->preloaded = image_preloaded;
524     image_buf = NULL;
525     image_preloaded = false;
526   }
527
528   ret = AVB_SLOT_VERIFY_RESULT_OK;
529
530 out:
531   /* Free the current buffer if any. */
532   if (image_buf != NULL && !image_preloaded) {
533     avb_free(image_buf);
534   }
535   /* Buffers that are already saved in slot_data will be handled by the caller
536    * even on failure. */
537   return ret;
538 }
539
540 static AvbSlotVerifyResult load_and_verify_vbmeta(
541     AvbOps* ops,
542     const char* const* requested_partitions,
543     const char* ab_suffix,
544     AvbSlotVerifyFlags flags,
545     bool allow_verification_error,
546     AvbVBMetaImageFlags toplevel_vbmeta_flags,
547     int rollback_index_location,
548     const char* partition_name,
549     size_t partition_name_len,
550     const uint8_t* expected_public_key,
551     size_t expected_public_key_length,
552     AvbSlotVerifyData* slot_data,
553     AvbAlgorithmType* out_algorithm_type,
554     AvbCmdlineSubstList* out_additional_cmdline_subst) {
555   char full_partition_name[AVB_PART_NAME_MAX_SIZE];
556   AvbSlotVerifyResult ret;
557   AvbIOResult io_ret;
558   size_t vbmeta_offset;
559   size_t vbmeta_size;
560   uint8_t* vbmeta_buf = NULL;
561   size_t vbmeta_num_read;
562   AvbVBMetaVerifyResult vbmeta_ret;
563   const uint8_t* pk_data;
564   size_t pk_len;
565   AvbVBMetaImageHeader vbmeta_header;
566   uint64_t stored_rollback_index;
567   const AvbDescriptor** descriptors = NULL;
568   size_t num_descriptors;
569   size_t n;
570   bool is_main_vbmeta;
571   bool look_for_vbmeta_footer;
572   AvbVBMetaData* vbmeta_image_data = NULL;
573
574   ret = AVB_SLOT_VERIFY_RESULT_OK;
575
576   avb_assert(slot_data != NULL);
577
578   /* Since we allow top-level vbmeta in 'boot', use
579    * rollback_index_location to determine whether we're the main
580    * vbmeta struct.
581    */
582   is_main_vbmeta = false;
583   if (rollback_index_location == 0) {
584     if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
585       is_main_vbmeta = true;
586     }
587   }
588
589   /* Don't use footers for vbmeta partitions ('vbmeta' or
590    * 'vbmeta_<partition_name>').
591    */
592   look_for_vbmeta_footer = true;
593   if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
594     look_for_vbmeta_footer = false;
595   }
596
597   if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
598     avb_error("Partition name is not valid UTF-8.\n");
599     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
600     goto out;
601   }
602
603   /* Construct full partition name e.g. system_a. */
604   if (!avb_str_concat(full_partition_name,
605                       sizeof full_partition_name,
606                       partition_name,
607                       partition_name_len,
608                       ab_suffix,
609                       avb_strlen(ab_suffix))) {
610     avb_error("Partition name and suffix does not fit.\n");
611     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
612     goto out;
613   }
614
615   /* If we're loading from the main vbmeta partition, the vbmeta struct is in
616    * the beginning. Otherwise we may have to locate it via a footer... if no
617    * footer is found, we look in the beginning to support e.g. vbmeta_<org>
618    * partitions holding data for e.g. super partitions (b/80195851 for
619    * rationale).
620    */
621   vbmeta_offset = 0;
622   vbmeta_size = VBMETA_MAX_SIZE;
623   if (look_for_vbmeta_footer) {
624     uint8_t footer_buf[AVB_FOOTER_SIZE];
625     size_t footer_num_read;
626     AvbFooter footer;
627
628     io_ret = ops->read_from_partition(ops,
629                                       full_partition_name,
630                                       -AVB_FOOTER_SIZE,
631                                       AVB_FOOTER_SIZE,
632                                       footer_buf,
633                                       &footer_num_read);
634     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
635       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
636       goto out;
637     } else if (io_ret != AVB_IO_RESULT_OK) {
638       avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
639       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
640       goto out;
641     }
642     avb_assert(footer_num_read == AVB_FOOTER_SIZE);
643
644     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
645                                           &footer)) {
646       avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
647     } else {
648       /* Basic footer sanity check since the data is untrusted. */
649       if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
650         avb_errorv(
651             full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
652       } else {
653         vbmeta_offset = footer.vbmeta_offset;
654         vbmeta_size = footer.vbmeta_size;
655       }
656     }
657   }
658
659   vbmeta_buf = avb_malloc(vbmeta_size);
660   if (vbmeta_buf == NULL) {
661     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
662     goto out;
663   }
664
665   if (vbmeta_offset != 0) {
666     avb_debugv("Loading vbmeta struct in footer from partition '",
667                full_partition_name,
668                "'.\n",
669                NULL);
670   } else {
671     avb_debugv("Loading vbmeta struct from partition '",
672                full_partition_name,
673                "'.\n",
674                NULL);
675   }
676
677   io_ret = ops->read_from_partition(ops,
678                                     full_partition_name,
679                                     vbmeta_offset,
680                                     vbmeta_size,
681                                     vbmeta_buf,
682                                     &vbmeta_num_read);
683   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
684     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
685     goto out;
686   } else if (io_ret != AVB_IO_RESULT_OK) {
687     /* If we're looking for 'vbmeta' but there is no such partition,
688      * go try to get it from the boot partition instead.
689      */
690     if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
691         !look_for_vbmeta_footer) {
692       avb_debugv(full_partition_name,
693                  ": No such partition. Trying 'boot' instead.\n",
694                  NULL);
695       ret = load_and_verify_vbmeta(ops,
696                                    requested_partitions,
697                                    ab_suffix,
698                                    flags,
699                                    allow_verification_error,
700                                    0 /* toplevel_vbmeta_flags */,
701                                    0 /* rollback_index_location */,
702                                    "boot",
703                                    avb_strlen("boot"),
704                                    NULL /* expected_public_key */,
705                                    0 /* expected_public_key_length */,
706                                    slot_data,
707                                    out_algorithm_type,
708                                    out_additional_cmdline_subst);
709       goto out;
710     } else {
711       avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
712       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
713       goto out;
714     }
715   }
716   avb_assert(vbmeta_num_read <= vbmeta_size);
717
718   /* Check if the image is properly signed and get the public key used
719    * to sign the image.
720    */
721   vbmeta_ret =
722       avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
723   switch (vbmeta_ret) {
724     case AVB_VBMETA_VERIFY_RESULT_OK:
725       avb_assert(pk_data != NULL && pk_len > 0);
726       break;
727
728     case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
729     case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
730     case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
731       ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
732       avb_errorv(full_partition_name,
733                  ": Error verifying vbmeta image: ",
734                  avb_vbmeta_verify_result_to_string(vbmeta_ret),
735                  "\n",
736                  NULL);
737       if (!allow_verification_error) {
738         goto out;
739       }
740       break;
741
742     case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
743       /* No way to continue this case. */
744       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
745       avb_errorv(full_partition_name,
746                  ": Error verifying vbmeta image: invalid vbmeta header\n",
747                  NULL);
748       goto out;
749
750     case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
751       /* No way to continue this case. */
752       ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
753       avb_errorv(full_partition_name,
754                  ": Error verifying vbmeta image: unsupported AVB version\n",
755                  NULL);
756       goto out;
757   }
758
759   /* Byteswap the header. */
760   avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
761                                              &vbmeta_header);
762
763   /* If we're the toplevel, assign flags so they'll be passed down. */
764   if (is_main_vbmeta) {
765     toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
766   } else {
767     if (vbmeta_header.flags != 0) {
768       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
769       avb_errorv(full_partition_name,
770                  ": chained vbmeta image has non-zero flags\n",
771                  NULL);
772       goto out;
773     }
774   }
775
776   uint32_t rollback_index_location_to_use = rollback_index_location;
777
778   /* Check if key used to make signature matches what is expected. */
779   if (pk_data != NULL) {
780     if (expected_public_key != NULL) {
781       avb_assert(!is_main_vbmeta);
782       if (expected_public_key_length != pk_len ||
783           avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
784         avb_errorv(full_partition_name,
785                    ": Public key used to sign data does not match key in chain "
786                    "partition descriptor.\n",
787                    NULL);
788         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
789         if (!allow_verification_error) {
790           goto out;
791         }
792       }
793     } else {
794       bool key_is_trusted = false;
795       const uint8_t* pk_metadata = NULL;
796       size_t pk_metadata_len = 0;
797
798       if (vbmeta_header.public_key_metadata_size > 0) {
799         pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
800                       vbmeta_header.authentication_data_block_size +
801                       vbmeta_header.public_key_metadata_offset;
802         pk_metadata_len = vbmeta_header.public_key_metadata_size;
803       }
804
805       // If we're not using a vbmeta partition, need to use another AvbOps...
806       if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
807         io_ret = ops->validate_public_key_for_partition(
808             ops,
809             full_partition_name,
810             pk_data,
811             pk_len,
812             pk_metadata,
813             pk_metadata_len,
814             &key_is_trusted,
815             &rollback_index_location_to_use);
816       } else {
817         avb_assert(is_main_vbmeta);
818         io_ret = ops->validate_vbmeta_public_key(ops,
819                                                  pk_data,
820                                                  pk_len,
821                                                  pk_metadata,
822                                                  pk_metadata_len,
823                                                  &key_is_trusted);
824       }
825
826       if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
827         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
828         goto out;
829       } else if (io_ret != AVB_IO_RESULT_OK) {
830         avb_errorv(full_partition_name,
831                    ": Error while checking public key used to sign data.\n",
832                    NULL);
833         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
834         goto out;
835       }
836       if (!key_is_trusted) {
837         avb_errorv(full_partition_name,
838                    ": Public key used to sign data rejected.\n",
839                    NULL);
840         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
841         if (!allow_verification_error) {
842           goto out;
843         }
844       }
845     }
846   }
847
848   /* Check rollback index. */
849   io_ret = ops->read_rollback_index(
850       ops, rollback_index_location_to_use, &stored_rollback_index);
851   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
852     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
853     goto out;
854   } else if (io_ret != AVB_IO_RESULT_OK) {
855     avb_errorv(full_partition_name,
856                ": Error getting rollback index for location.\n",
857                NULL);
858     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
859     goto out;
860   }
861   if (vbmeta_header.rollback_index < stored_rollback_index) {
862     avb_errorv(
863         full_partition_name,
864         ": Image rollback index is less than the stored rollback index.\n",
865         NULL);
866     ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
867     if (!allow_verification_error) {
868       goto out;
869     }
870   }
871
872   /* Copy vbmeta to vbmeta_images before recursing. */
873   if (is_main_vbmeta) {
874     avb_assert(slot_data->num_vbmeta_images == 0);
875   } else {
876     if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
877       avb_assert(slot_data->num_vbmeta_images > 0);
878     }
879   }
880   if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
881     avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
882     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
883     goto out;
884   }
885   vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
886   vbmeta_image_data->partition_name = avb_strdup(partition_name);
887   vbmeta_image_data->vbmeta_data = vbmeta_buf;
888   /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
889    * and this includes data past the end of the image. Pass the
890    * actual size of the vbmeta image. Also, no need to use
891    * avb_safe_add() since the header has already been verified.
892    */
893   vbmeta_image_data->vbmeta_size =
894       sizeof(AvbVBMetaImageHeader) +
895       vbmeta_header.authentication_data_block_size +
896       vbmeta_header.auxiliary_data_block_size;
897   vbmeta_image_data->verify_result = vbmeta_ret;
898
899   /* If verification has been disabled by setting a bit in the image,
900    * we're done... except that we need to load the entirety of the
901    * requested partitions.
902    */
903   if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
904     AvbSlotVerifyResult sub_ret;
905     avb_debugv(
906         full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
907     /* If load_requested_partitions() fail it is always a fatal
908      * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
909      * than recoverable (e.g. one where result_should_continue()
910      * returns true) and we want to convey that error.
911      */
912     sub_ret = load_requested_partitions(
913         ops, requested_partitions, ab_suffix, slot_data);
914     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
915       ret = sub_ret;
916     }
917     goto out;
918   }
919
920   /* Now go through all descriptors and take the appropriate action:
921    *
922    * - hash descriptor: Load data from partition, calculate hash, and
923    *   checks that it matches what's in the hash descriptor.
924    *
925    * - hashtree descriptor: Do nothing since verification happens
926    *   on-the-fly from within the OS. (Unless the descriptor uses a
927    *   persistent digest, in which case we need to find it).
928    *
929    * - chained partition descriptor: Load the footer, load the vbmeta
930    *   image, verify vbmeta image (includes rollback checks, hash
931    *   checks, bail on chained partitions).
932    */
933   descriptors =
934       avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
935   for (n = 0; n < num_descriptors; n++) {
936     AvbDescriptor desc;
937
938     if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
939       avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
940       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
941       goto out;
942     }
943
944     switch (desc.tag) {
945       case AVB_DESCRIPTOR_TAG_HASH: {
946         AvbSlotVerifyResult sub_ret;
947         sub_ret = load_and_verify_hash_partition(ops,
948                                                  requested_partitions,
949                                                  ab_suffix,
950                                                  allow_verification_error,
951                                                  descriptors[n],
952                                                  slot_data);
953         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
954           ret = sub_ret;
955           if (!allow_verification_error || !result_should_continue(ret)) {
956             goto out;
957           }
958         }
959       } break;
960
961       case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
962         AvbSlotVerifyResult sub_ret;
963         AvbChainPartitionDescriptor chain_desc;
964         const uint8_t* chain_partition_name;
965         const uint8_t* chain_public_key;
966
967         /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
968         if (!is_main_vbmeta) {
969           avb_errorv(full_partition_name,
970                      ": Encountered chain descriptor not in main image.\n",
971                      NULL);
972           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
973           goto out;
974         }
975
976         if (!avb_chain_partition_descriptor_validate_and_byteswap(
977                 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
978           avb_errorv(full_partition_name,
979                      ": Chain partition descriptor is invalid.\n",
980                      NULL);
981           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
982           goto out;
983         }
984
985         if (chain_desc.rollback_index_location == 0) {
986           avb_errorv(full_partition_name,
987                      ": Chain partition has invalid "
988                      "rollback_index_location field.\n",
989                      NULL);
990           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
991           goto out;
992         }
993
994         chain_partition_name = ((const uint8_t*)descriptors[n]) +
995                                sizeof(AvbChainPartitionDescriptor);
996         chain_public_key = chain_partition_name + chain_desc.partition_name_len;
997
998         sub_ret =
999             load_and_verify_vbmeta(ops,
1000                                    requested_partitions,
1001                                    ab_suffix,
1002                                    flags,
1003                                    allow_verification_error,
1004                                    toplevel_vbmeta_flags,
1005                                    chain_desc.rollback_index_location,
1006                                    (const char*)chain_partition_name,
1007                                    chain_desc.partition_name_len,
1008                                    chain_public_key,
1009                                    chain_desc.public_key_len,
1010                                    slot_data,
1011                                    NULL, /* out_algorithm_type */
1012                                    NULL /* out_additional_cmdline_subst */);
1013         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1014           ret = sub_ret;
1015           if (!result_should_continue(ret)) {
1016             goto out;
1017           }
1018         }
1019       } break;
1020
1021       case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
1022         const uint8_t* kernel_cmdline;
1023         AvbKernelCmdlineDescriptor kernel_cmdline_desc;
1024         bool apply_cmdline;
1025
1026         if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
1027                 (AvbKernelCmdlineDescriptor*)descriptors[n],
1028                 &kernel_cmdline_desc)) {
1029           avb_errorv(full_partition_name,
1030                      ": Kernel cmdline descriptor is invalid.\n",
1031                      NULL);
1032           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1033           goto out;
1034         }
1035
1036         kernel_cmdline = ((const uint8_t*)descriptors[n]) +
1037                          sizeof(AvbKernelCmdlineDescriptor);
1038
1039         if (!avb_validate_utf8(kernel_cmdline,
1040                                kernel_cmdline_desc.kernel_cmdline_length)) {
1041           avb_errorv(full_partition_name,
1042                      ": Kernel cmdline is not valid UTF-8.\n",
1043                      NULL);
1044           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1045           goto out;
1046         }
1047
1048         /* Compare the flags for top-level VBMeta struct with flags in
1049          * the command-line descriptor so command-line snippets only
1050          * intended for a certain mode (dm-verity enabled/disabled)
1051          * are skipped if applicable.
1052          */
1053         apply_cmdline = true;
1054         if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1055           if (kernel_cmdline_desc.flags &
1056               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
1057             apply_cmdline = false;
1058           }
1059         } else {
1060           if (kernel_cmdline_desc.flags &
1061               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
1062             apply_cmdline = false;
1063           }
1064         }
1065
1066         if (apply_cmdline) {
1067           if (slot_data->cmdline == NULL) {
1068             slot_data->cmdline =
1069                 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
1070             if (slot_data->cmdline == NULL) {
1071               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1072               goto out;
1073             }
1074             avb_memcpy(slot_data->cmdline,
1075                        kernel_cmdline,
1076                        kernel_cmdline_desc.kernel_cmdline_length);
1077           } else {
1078             /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
1079             size_t orig_size = avb_strlen(slot_data->cmdline);
1080             size_t new_size =
1081                 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
1082             char* new_cmdline = avb_calloc(new_size);
1083             if (new_cmdline == NULL) {
1084               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1085               goto out;
1086             }
1087             avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
1088             new_cmdline[orig_size] = ' ';
1089             avb_memcpy(new_cmdline + orig_size + 1,
1090                        kernel_cmdline,
1091                        kernel_cmdline_desc.kernel_cmdline_length);
1092             avb_free(slot_data->cmdline);
1093             slot_data->cmdline = new_cmdline;
1094           }
1095         }
1096       } break;
1097
1098       case AVB_DESCRIPTOR_TAG_HASHTREE: {
1099         AvbHashtreeDescriptor hashtree_desc;
1100
1101         if (!avb_hashtree_descriptor_validate_and_byteswap(
1102                 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
1103           avb_errorv(
1104               full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
1105           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1106           goto out;
1107         }
1108
1109         /* We only need to continue when there is no digest in the descriptor.
1110          * This is because the only processing here is to find the digest and
1111          * make it available on the kernel command line.
1112          */
1113         if (hashtree_desc.root_digest_len == 0) {
1114           char part_name[AVB_PART_NAME_MAX_SIZE];
1115           size_t digest_len = 0;
1116           uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
1117           const uint8_t* desc_partition_name =
1118               ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
1119
1120           if (!avb_validate_utf8(desc_partition_name,
1121                                  hashtree_desc.partition_name_len)) {
1122             avb_error("Partition name is not valid UTF-8.\n");
1123             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1124             goto out;
1125           }
1126
1127           /* No ab_suffix for partitions without a digest in the descriptor
1128            * because these partitions hold data unique to this device and are
1129            * not updated using an A/B scheme.
1130            */
1131           if ((hashtree_desc.flags &
1132                AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
1133               avb_strlen(ab_suffix) != 0) {
1134             avb_error("Cannot use A/B with a persistent root digest.\n");
1135             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1136             goto out;
1137           }
1138           if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
1139             avb_error("Partition name does not fit.\n");
1140             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1141             goto out;
1142           }
1143           avb_memcpy(
1144               part_name, desc_partition_name, hashtree_desc.partition_name_len);
1145           part_name[hashtree_desc.partition_name_len] = '\0';
1146
1147           /* Determine the expected digest size from the hash algorithm. */
1148           if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1149               0) {
1150             digest_len = AVB_SHA1_DIGEST_SIZE;
1151           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1152                                 "sha256") == 0) {
1153             digest_len = AVB_SHA256_DIGEST_SIZE;
1154           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1155                                 "sha512") == 0) {
1156             digest_len = AVB_SHA512_DIGEST_SIZE;
1157           } else {
1158             avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1159             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1160             goto out;
1161           }
1162
1163           ret = read_persistent_digest(ops,
1164                                        part_name,
1165                                        digest_len,
1166                                        NULL /* initial_digest */,
1167                                        digest_buf);
1168           if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1169             goto out;
1170           }
1171
1172           if (out_additional_cmdline_subst) {
1173             ret =
1174                 avb_add_root_digest_substitution(part_name,
1175                                                  digest_buf,
1176                                                  digest_len,
1177                                                  out_additional_cmdline_subst);
1178             if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1179               goto out;
1180             }
1181           }
1182         }
1183       } break;
1184
1185       case AVB_DESCRIPTOR_TAG_PROPERTY:
1186         /* Do nothing. */
1187         break;
1188     }
1189   }
1190
1191   if (rollback_index_location < 0 ||
1192       rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1193     avb_errorv(
1194         full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1195     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1196     goto out;
1197   }
1198
1199   slot_data->rollback_indexes[rollback_index_location] =
1200       vbmeta_header.rollback_index;
1201
1202   if (out_algorithm_type != NULL) {
1203     *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1204   }
1205
1206 out:
1207   /* If |vbmeta_image_data| isn't NULL it means that it adopted
1208    * |vbmeta_buf| so in that case don't free it here.
1209    */
1210   if (vbmeta_image_data == NULL) {
1211     if (vbmeta_buf != NULL) {
1212       avb_free(vbmeta_buf);
1213     }
1214   }
1215   if (descriptors != NULL) {
1216     avb_free(descriptors);
1217   }
1218   return ret;
1219 }
1220
1221 static AvbIOResult avb_manage_hashtree_error_mode(
1222     AvbOps* ops,
1223     AvbSlotVerifyFlags flags,
1224     AvbSlotVerifyData* data,
1225     AvbHashtreeErrorMode* out_hashtree_error_mode) {
1226   AvbHashtreeErrorMode ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1227   AvbIOResult io_ret = AVB_IO_RESULT_OK;
1228   uint8_t vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1229   uint8_t stored_vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1230   size_t num_bytes_read;
1231
1232   avb_assert(out_hashtree_error_mode != NULL);
1233   avb_assert(ops->read_persistent_value != NULL);
1234   avb_assert(ops->write_persistent_value != NULL);
1235
1236   // If we're rebooting because of dm-verity corruption, make a note of
1237   // the vbmeta hash so we can stay in 'eio' mode until things change.
1238   if (flags & AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION) {
1239     avb_debug(
1240         "Rebooting because of dm-verity corruption - "
1241         "recording OS instance and using 'eio' mode.\n");
1242     avb_slot_verify_data_calculate_vbmeta_digest(
1243         data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1244     io_ret = ops->write_persistent_value(ops,
1245                                          AVB_NPV_MANAGED_VERITY_MODE,
1246                                          AVB_SHA256_DIGEST_SIZE,
1247                                          vbmeta_digest_sha256);
1248     if (io_ret != AVB_IO_RESULT_OK) {
1249       avb_error("Error writing to " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1250       goto out;
1251     }
1252     ret = AVB_HASHTREE_ERROR_MODE_EIO;
1253     io_ret = AVB_IO_RESULT_OK;
1254     goto out;
1255   }
1256
1257   // See if we're in 'eio' mode.
1258   io_ret = ops->read_persistent_value(ops,
1259                                       AVB_NPV_MANAGED_VERITY_MODE,
1260                                       AVB_SHA256_DIGEST_SIZE,
1261                                       stored_vbmeta_digest_sha256,
1262                                       &num_bytes_read);
1263   if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE ||
1264       (io_ret == AVB_IO_RESULT_OK && num_bytes_read == 0)) {
1265     // This is the usual case ('eio' mode not set).
1266     avb_debug("No dm-verity corruption - using in 'restart' mode.\n");
1267     ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1268     io_ret = AVB_IO_RESULT_OK;
1269     goto out;
1270   } else if (io_ret != AVB_IO_RESULT_OK) {
1271     avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1272     goto out;
1273   }
1274   if (num_bytes_read != AVB_SHA256_DIGEST_SIZE) {
1275     avb_error(
1276         "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
1277         ".\n");
1278     io_ret = AVB_IO_RESULT_ERROR_IO;
1279     goto out;
1280   }
1281
1282   // OK, so we're currently in 'eio' mode and the vbmeta digest of the OS
1283   // that caused this is in |stored_vbmeta_digest_sha256| ... now see if
1284   // the OS we're dealing with now is the same.
1285   avb_slot_verify_data_calculate_vbmeta_digest(
1286       data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1287   if (avb_memcmp(vbmeta_digest_sha256,
1288                  stored_vbmeta_digest_sha256,
1289                  AVB_SHA256_DIGEST_SIZE) == 0) {
1290     // It's the same so we're still in 'eio' mode.
1291     avb_debug("Same OS instance detected - staying in 'eio' mode.\n");
1292     ret = AVB_HASHTREE_ERROR_MODE_EIO;
1293     io_ret = AVB_IO_RESULT_OK;
1294   } else {
1295     // It did change!
1296     avb_debug(
1297         "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
1298     io_ret =
1299         ops->write_persistent_value(ops,
1300                                     AVB_NPV_MANAGED_VERITY_MODE,
1301                                     0,  // This clears the persistent property.
1302                                     vbmeta_digest_sha256);
1303     if (io_ret != AVB_IO_RESULT_OK) {
1304       avb_error("Error clearing " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1305       goto out;
1306     }
1307     ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1308     io_ret = AVB_IO_RESULT_OK;
1309   }
1310
1311 out:
1312   *out_hashtree_error_mode = ret;
1313   return io_ret;
1314 }
1315
1316 static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
1317   char part_name[AVB_PART_NAME_MAX_SIZE];
1318   char* system_part_name = "system";
1319   char guid_buf[37];
1320   AvbIOResult io_ret;
1321
1322   if (!avb_str_concat(part_name,
1323                       sizeof part_name,
1324                       system_part_name,
1325                       avb_strlen(system_part_name),
1326                       ab_suffix,
1327                       avb_strlen(ab_suffix))) {
1328     avb_error("System partition name and suffix does not fit.\n");
1329     return false;
1330   }
1331
1332   io_ret = ops->get_unique_guid_for_partition(
1333       ops, part_name, guid_buf, sizeof guid_buf);
1334   if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
1335     avb_debug("No system partition.\n");
1336     return false;
1337   } else if (io_ret != AVB_IO_RESULT_OK) {
1338     avb_error("Error getting unique GUID for system partition.\n");
1339     return false;
1340   }
1341
1342   return true;
1343 }
1344
1345 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1346                                     const char* const* requested_partitions,
1347                                     const char* ab_suffix,
1348                                     AvbSlotVerifyFlags flags,
1349                                     AvbHashtreeErrorMode hashtree_error_mode,
1350                                     AvbSlotVerifyData** out_data) {
1351   AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1352   AvbSlotVerifyData* slot_data = NULL;
1353   AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1354   bool using_boot_for_vbmeta = false;
1355   AvbVBMetaImageHeader toplevel_vbmeta;
1356   bool allow_verification_error =
1357       (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1358   AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1359
1360   /* Fail early if we're missing the AvbOps needed for slot verification. */
1361   avb_assert(ops->read_is_device_unlocked != NULL);
1362   avb_assert(ops->read_from_partition != NULL);
1363   avb_assert(ops->get_size_of_partition != NULL);
1364   avb_assert(ops->read_rollback_index != NULL);
1365   avb_assert(ops->get_unique_guid_for_partition != NULL);
1366
1367   if (out_data != NULL) {
1368     *out_data = NULL;
1369   }
1370
1371   /* Allowing dm-verity errors defeats the purpose of verified boot so
1372    * only allow this if set up to allow verification errors
1373    * (e.g. typically only UNLOCKED mode).
1374    */
1375   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1376       !allow_verification_error) {
1377     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1378     goto fail;
1379   }
1380
1381   /* Make sure passed-in AvbOps support persistent values if
1382    * asking for libavb to manage verity state.
1383    */
1384   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1385     if (ops->read_persistent_value == NULL ||
1386         ops->write_persistent_value == NULL) {
1387       avb_error(
1388           "Persistent values required for "
1389           "AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO "
1390           "but are not implemented in given AvbOps.\n");
1391       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1392       goto fail;
1393     }
1394   }
1395
1396   /* Make sure passed-in AvbOps support verifying public keys and getting
1397    * rollback index location if not using a vbmeta partition.
1398    */
1399   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1400     if (ops->validate_public_key_for_partition == NULL) {
1401       avb_error(
1402           "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
1403           "validate_public_key_for_partition() operation isn't implemented.\n");
1404       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1405       goto fail;
1406     }
1407   } else {
1408     avb_assert(ops->validate_vbmeta_public_key != NULL);
1409   }
1410
1411   slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1412   if (slot_data == NULL) {
1413     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1414     goto fail;
1415   }
1416   slot_data->vbmeta_images =
1417       avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1418   if (slot_data->vbmeta_images == NULL) {
1419     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1420     goto fail;
1421   }
1422   slot_data->loaded_partitions =
1423       avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1424   if (slot_data->loaded_partitions == NULL) {
1425     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1426     goto fail;
1427   }
1428
1429   additional_cmdline_subst = avb_new_cmdline_subst_list();
1430   if (additional_cmdline_subst == NULL) {
1431     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1432     goto fail;
1433   }
1434
1435   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1436     if (requested_partitions == NULL || requested_partitions[0] == NULL) {
1437       avb_fatal(
1438           "Requested partitions cannot be empty when using "
1439           "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
1440       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1441       goto fail;
1442     }
1443
1444     /* No vbmeta partition, go through each of the requested partitions... */
1445     for (size_t n = 0; requested_partitions[n] != NULL; n++) {
1446       ret = load_and_verify_vbmeta(ops,
1447                                    requested_partitions,
1448                                    ab_suffix,
1449                                    flags,
1450                                    allow_verification_error,
1451                                    0 /* toplevel_vbmeta_flags */,
1452                                    0 /* rollback_index_location */,
1453                                    requested_partitions[n],
1454                                    avb_strlen(requested_partitions[n]),
1455                                    NULL /* expected_public_key */,
1456                                    0 /* expected_public_key_length */,
1457                                    slot_data,
1458                                    &algorithm_type,
1459                                    additional_cmdline_subst);
1460       if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1461         goto fail;
1462       }
1463     }
1464
1465   } else {
1466     /* Usual path, load "vbmeta"... */
1467     ret = load_and_verify_vbmeta(ops,
1468                                  requested_partitions,
1469                                  ab_suffix,
1470                                  flags,
1471                                  allow_verification_error,
1472                                  0 /* toplevel_vbmeta_flags */,
1473                                  0 /* rollback_index_location */,
1474                                  "vbmeta",
1475                                  avb_strlen("vbmeta"),
1476                                  NULL /* expected_public_key */,
1477                                  0 /* expected_public_key_length */,
1478                                  slot_data,
1479                                  &algorithm_type,
1480                                  additional_cmdline_subst);
1481     if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1482       goto fail;
1483     }
1484   }
1485
1486   if (!result_should_continue(ret)) {
1487     goto fail;
1488   }
1489
1490   /* If things check out, mangle the kernel command-line as needed. */
1491   if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
1492     if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1493       avb_assert(
1494           avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1495       using_boot_for_vbmeta = true;
1496     }
1497   }
1498
1499   /* Byteswap top-level vbmeta header since we'll need it below. */
1500   avb_vbmeta_image_header_to_host_byte_order(
1501       (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1502       &toplevel_vbmeta);
1503
1504   /* Fill in |ab_suffix| field. */
1505   slot_data->ab_suffix = avb_strdup(ab_suffix);
1506   if (slot_data->ab_suffix == NULL) {
1507     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1508     goto fail;
1509   }
1510
1511   /* If verification is disabled, we are done ... we specifically
1512    * don't want to add any androidboot.* options since verification
1513    * is disabled.
1514    */
1515   if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1516     /* Since verification is disabled we didn't process any
1517      * descriptors and thus there's no cmdline... so set root= such
1518      * that the system partition is mounted.
1519      */
1520     avb_assert(slot_data->cmdline == NULL);
1521     // Devices with dynamic partitions won't have system partition.
1522     // Instead, it has a large super partition to accommodate *.img files.
1523     // See b/119551429 for details.
1524     if (has_system_partition(ops, ab_suffix)) {
1525       slot_data->cmdline =
1526           avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1527     } else {
1528       // The |cmdline| field should be a NUL-terminated string.
1529       slot_data->cmdline = avb_strdup("");
1530     }
1531     if (slot_data->cmdline == NULL) {
1532       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1533       goto fail;
1534     }
1535   } else {
1536     /* If requested, manage dm-verity mode... */
1537     AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
1538     if (hashtree_error_mode ==
1539         AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1540       AvbIOResult io_ret;
1541       io_ret = avb_manage_hashtree_error_mode(
1542           ops, flags, slot_data, &resolved_hashtree_error_mode);
1543       if (io_ret != AVB_IO_RESULT_OK) {
1544         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1545         if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1546           ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1547         }
1548         goto fail;
1549       }
1550     }
1551     slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
1552
1553     /* Add options... */
1554     AvbSlotVerifyResult sub_ret;
1555     sub_ret = avb_append_options(ops,
1556                                  flags,
1557                                  slot_data,
1558                                  &toplevel_vbmeta,
1559                                  algorithm_type,
1560                                  hashtree_error_mode,
1561                                  resolved_hashtree_error_mode);
1562     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1563       ret = sub_ret;
1564       goto fail;
1565     }
1566   }
1567
1568   /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1569   if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
1570     char* new_cmdline;
1571     new_cmdline = avb_sub_cmdline(ops,
1572                                   slot_data->cmdline,
1573                                   ab_suffix,
1574                                   using_boot_for_vbmeta,
1575                                   additional_cmdline_subst);
1576     if (new_cmdline != slot_data->cmdline) {
1577       if (new_cmdline == NULL) {
1578         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1579         goto fail;
1580       }
1581       avb_free(slot_data->cmdline);
1582       slot_data->cmdline = new_cmdline;
1583     }
1584   }
1585
1586   if (out_data != NULL) {
1587     *out_data = slot_data;
1588   } else {
1589     avb_slot_verify_data_free(slot_data);
1590   }
1591
1592   avb_free_cmdline_subst_list(additional_cmdline_subst);
1593   additional_cmdline_subst = NULL;
1594
1595   if (!allow_verification_error) {
1596     avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1597   }
1598
1599   return ret;
1600
1601 fail:
1602   if (slot_data != NULL) {
1603     avb_slot_verify_data_free(slot_data);
1604   }
1605   if (additional_cmdline_subst != NULL) {
1606     avb_free_cmdline_subst_list(additional_cmdline_subst);
1607   }
1608   return ret;
1609 }
1610
1611 void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1612   if (data->ab_suffix != NULL) {
1613     avb_free(data->ab_suffix);
1614   }
1615   if (data->cmdline != NULL) {
1616     avb_free(data->cmdline);
1617   }
1618   if (data->vbmeta_images != NULL) {
1619     size_t n;
1620     for (n = 0; n < data->num_vbmeta_images; n++) {
1621       AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1622       if (vbmeta_image->partition_name != NULL) {
1623         avb_free(vbmeta_image->partition_name);
1624       }
1625       if (vbmeta_image->vbmeta_data != NULL) {
1626         avb_free(vbmeta_image->vbmeta_data);
1627       }
1628     }
1629     avb_free(data->vbmeta_images);
1630   }
1631   if (data->loaded_partitions != NULL) {
1632     size_t n;
1633     for (n = 0; n < data->num_loaded_partitions; n++) {
1634       AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1635       if (loaded_partition->partition_name != NULL) {
1636         avb_free(loaded_partition->partition_name);
1637       }
1638       if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1639         avb_free(loaded_partition->data);
1640       }
1641     }
1642     avb_free(data->loaded_partitions);
1643   }
1644   avb_free(data);
1645 }
1646
1647 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1648   const char* ret = NULL;
1649
1650   switch (result) {
1651     case AVB_SLOT_VERIFY_RESULT_OK:
1652       ret = "OK";
1653       break;
1654     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1655       ret = "ERROR_OOM";
1656       break;
1657     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1658       ret = "ERROR_IO";
1659       break;
1660     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1661       ret = "ERROR_VERIFICATION";
1662       break;
1663     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1664       ret = "ERROR_ROLLBACK_INDEX";
1665       break;
1666     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1667       ret = "ERROR_PUBLIC_KEY_REJECTED";
1668       break;
1669     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1670       ret = "ERROR_INVALID_METADATA";
1671       break;
1672     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1673       ret = "ERROR_UNSUPPORTED_VERSION";
1674       break;
1675     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1676       ret = "ERROR_INVALID_ARGUMENT";
1677       break;
1678       /* Do not add a 'default:' case here because of -Wswitch. */
1679   }
1680
1681   if (ret == NULL) {
1682     avb_error("Unknown AvbSlotVerifyResult value.\n");
1683     ret = "(unknown)";
1684   }
1685
1686   return ret;
1687 }
1688
1689 void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
1690                                                   AvbDigestType digest_type,
1691                                                   uint8_t* out_digest) {
1692   bool ret = false;
1693   size_t n;
1694
1695   switch (digest_type) {
1696     case AVB_DIGEST_TYPE_SHA256: {
1697       AvbSHA256Ctx ctx;
1698       avb_sha256_init(&ctx);
1699       for (n = 0; n < data->num_vbmeta_images; n++) {
1700         avb_sha256_update(&ctx,
1701                           data->vbmeta_images[n].vbmeta_data,
1702                           data->vbmeta_images[n].vbmeta_size);
1703       }
1704       avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
1705       ret = true;
1706     } break;
1707
1708     case AVB_DIGEST_TYPE_SHA512: {
1709       AvbSHA512Ctx ctx;
1710       avb_sha512_init(&ctx);
1711       for (n = 0; n < data->num_vbmeta_images; n++) {
1712         avb_sha512_update(&ctx,
1713                           data->vbmeta_images[n].vbmeta_data,
1714                           data->vbmeta_images[n].vbmeta_size);
1715       }
1716       avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
1717       ret = true;
1718     } break;
1719
1720       /* Do not add a 'default:' case here because of -Wswitch. */
1721   }
1722
1723   if (!ret) {
1724     avb_fatal("Unknown digest type");
1725   }
1726 }