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