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