• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   // Although only one of the type might be used, we have to defined the
389   // structure here so that they would live outside the 'if/else' scope to be
390   // used later.
391   AvbSHA256Ctx sha256_ctx;
392   AvbSHA512Ctx sha512_ctx;
393   size_t image_size_to_hash = hash_desc.image_size;
394   // If we allow verification error and the whole partition is smaller than
395   // image size in hash descriptor, we just hash the whole partition.
396   if (image_size_to_hash > image_size) {
397     image_size_to_hash = image_size;
398   }
399   if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
400     avb_sha256_init(&sha256_ctx);
401     avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
402     avb_sha256_update(&sha256_ctx, image_buf, image_size_to_hash);
403     digest = avb_sha256_final(&sha256_ctx);
404     digest_len = AVB_SHA256_DIGEST_SIZE;
405   } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
406     avb_sha512_init(&sha512_ctx);
407     avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
408     avb_sha512_update(&sha512_ctx, image_buf, image_size_to_hash);
409     digest = avb_sha512_final(&sha512_ctx);
410     digest_len = AVB_SHA512_DIGEST_SIZE;
411   } else {
412     avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
413     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
414     goto out;
415   }
416 
417   if (hash_desc.digest_len == 0) {
418     /* Expect a match to a persistent digest. */
419     avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
420     expected_digest_len = digest_len;
421     expected_digest = expected_digest_buf;
422     avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
423     /* Pass |digest| as the |initial_digest| so devices not yet initialized get
424      * initialized to the current partition digest.
425      */
426     ret = read_persistent_digest(
427         ops, part_name, digest_len, digest, expected_digest_buf);
428     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
429       goto out;
430     }
431   } else {
432     /* Expect a match to the digest in the descriptor. */
433     expected_digest_len = hash_desc.digest_len;
434     expected_digest = desc_digest;
435   }
436 
437   if (digest_len != expected_digest_len) {
438     avb_errorv(
439         part_name, ": Digest in descriptor not of expected size.\n", NULL);
440     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
441     goto out;
442   }
443 
444   if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
445     avb_errorv(part_name,
446                ": Hash of data does not match digest in descriptor.\n",
447                NULL);
448     ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
449     goto out;
450   }
451 
452   ret = AVB_SLOT_VERIFY_RESULT_OK;
453 
454 out:
455 
456   /* If it worked and something was loaded, copy to slot_data. */
457   if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
458       image_buf != NULL) {
459     AvbPartitionData* loaded_partition;
460     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
461       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
462       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
463       goto fail;
464     }
465     loaded_partition =
466         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
467     loaded_partition->partition_name = avb_strdup(found);
468     loaded_partition->data_size = image_size;
469     loaded_partition->data = image_buf;
470     loaded_partition->preloaded = image_preloaded;
471     image_buf = NULL;
472   }
473 
474 fail:
475   if (image_buf != NULL && !image_preloaded) {
476     avb_free(image_buf);
477   }
478   return ret;
479 }
480 
load_requested_partitions(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,AvbSlotVerifyData * slot_data)481 static AvbSlotVerifyResult load_requested_partitions(
482     AvbOps* ops,
483     const char* const* requested_partitions,
484     const char* ab_suffix,
485     AvbSlotVerifyData* slot_data) {
486   AvbSlotVerifyResult ret;
487   uint8_t* image_buf = NULL;
488   bool image_preloaded = false;
489   size_t n;
490 
491   for (n = 0; requested_partitions[n] != NULL; n++) {
492     char part_name[AVB_PART_NAME_MAX_SIZE];
493     AvbIOResult io_ret;
494     uint64_t image_size;
495     AvbPartitionData* loaded_partition;
496 
497     if (!avb_str_concat(part_name,
498                         sizeof part_name,
499                         requested_partitions[n],
500                         avb_strlen(requested_partitions[n]),
501                         ab_suffix,
502                         avb_strlen(ab_suffix))) {
503       avb_error("Partition name and suffix does not fit.\n");
504       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
505       goto out;
506     }
507 
508     io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
509     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
510       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
511       goto out;
512     } else if (io_ret != AVB_IO_RESULT_OK) {
513       avb_errorv(part_name, ": Error determining partition size.\n", NULL);
514       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
515       goto out;
516     }
517     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
518 
519     ret = load_full_partition(
520         ops, part_name, image_size, &image_buf, &image_preloaded);
521     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
522       goto out;
523     }
524 
525     /* Move to slot_data. */
526     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
527       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
528       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
529       goto out;
530     }
531     loaded_partition =
532         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
533     loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
534     if (loaded_partition->partition_name == NULL) {
535       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
536       goto out;
537     }
538     loaded_partition->data_size = image_size;
539     loaded_partition->data = image_buf; /* Transferring the owner. */
540     loaded_partition->preloaded = image_preloaded;
541     image_buf = NULL;
542     image_preloaded = false;
543   }
544 
545   ret = AVB_SLOT_VERIFY_RESULT_OK;
546 
547 out:
548   /* Free the current buffer if any. */
549   if (image_buf != NULL && !image_preloaded) {
550     avb_free(image_buf);
551   }
552   /* Buffers that are already saved in slot_data will be handled by the caller
553    * even on failure. */
554   return ret;
555 }
556 
load_and_verify_vbmeta(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,AvbSlotVerifyFlags flags,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)557 static AvbSlotVerifyResult load_and_verify_vbmeta(
558     AvbOps* ops,
559     const char* const* requested_partitions,
560     const char* ab_suffix,
561     AvbSlotVerifyFlags flags,
562     bool allow_verification_error,
563     AvbVBMetaImageFlags toplevel_vbmeta_flags,
564     int rollback_index_location,
565     const char* partition_name,
566     size_t partition_name_len,
567     const uint8_t* expected_public_key,
568     size_t expected_public_key_length,
569     AvbSlotVerifyData* slot_data,
570     AvbAlgorithmType* out_algorithm_type,
571     AvbCmdlineSubstList* out_additional_cmdline_subst) {
572   char full_partition_name[AVB_PART_NAME_MAX_SIZE];
573   AvbSlotVerifyResult ret;
574   AvbIOResult io_ret;
575   uint64_t vbmeta_offset;
576   size_t vbmeta_size;
577   uint8_t* vbmeta_buf = NULL;
578   size_t vbmeta_num_read;
579   AvbVBMetaVerifyResult vbmeta_ret;
580   const uint8_t* pk_data;
581   size_t pk_len;
582   AvbVBMetaImageHeader vbmeta_header;
583   uint64_t stored_rollback_index;
584   const AvbDescriptor** descriptors = NULL;
585   size_t num_descriptors;
586   size_t n;
587   bool is_main_vbmeta;
588   bool look_for_vbmeta_footer;
589   AvbVBMetaData* vbmeta_image_data = NULL;
590 
591   ret = AVB_SLOT_VERIFY_RESULT_OK;
592 
593   avb_assert(slot_data != NULL);
594 
595   /* Since we allow top-level vbmeta in 'boot', use
596    * rollback_index_location to determine whether we're the main
597    * vbmeta struct.
598    */
599   is_main_vbmeta = false;
600   if (rollback_index_location == 0) {
601     if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
602       is_main_vbmeta = true;
603     }
604   }
605 
606   /* Don't use footers for vbmeta partitions ('vbmeta' or
607    * 'vbmeta_<partition_name>').
608    */
609   look_for_vbmeta_footer = true;
610   if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
611     look_for_vbmeta_footer = false;
612   }
613 
614   if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
615     avb_error("Partition name is not valid UTF-8.\n");
616     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
617     goto out;
618   }
619 
620   /* Construct full partition name e.g. system_a. */
621   if (!avb_str_concat(full_partition_name,
622                       sizeof full_partition_name,
623                       partition_name,
624                       partition_name_len,
625                       ab_suffix,
626                       avb_strlen(ab_suffix))) {
627     avb_error("Partition name and suffix does not fit.\n");
628     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
629     goto out;
630   }
631 
632   /* If we're loading from the main vbmeta partition, the vbmeta struct is in
633    * the beginning. Otherwise we may have to locate it via a footer... if no
634    * footer is found, we look in the beginning to support e.g. vbmeta_<org>
635    * partitions holding data for e.g. super partitions (b/80195851 for
636    * rationale).
637    */
638   vbmeta_offset = 0;
639   vbmeta_size = VBMETA_MAX_SIZE;
640   if (look_for_vbmeta_footer) {
641     uint8_t footer_buf[AVB_FOOTER_SIZE];
642     size_t footer_num_read;
643     AvbFooter footer;
644 
645     io_ret = ops->read_from_partition(ops,
646                                       full_partition_name,
647                                       -AVB_FOOTER_SIZE,
648                                       AVB_FOOTER_SIZE,
649                                       footer_buf,
650                                       &footer_num_read);
651     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
652       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
653       goto out;
654     } else if (io_ret != AVB_IO_RESULT_OK) {
655       avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
656       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
657       goto out;
658     }
659     avb_assert(footer_num_read == AVB_FOOTER_SIZE);
660 
661     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
662                                           &footer)) {
663       avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
664     } else {
665       /* Basic footer sanity check since the data is untrusted. */
666       if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
667         avb_errorv(
668             full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
669       } else {
670         vbmeta_offset = footer.vbmeta_offset;
671         vbmeta_size = footer.vbmeta_size;
672       }
673     }
674   }
675 
676   vbmeta_buf = avb_malloc(vbmeta_size);
677   if (vbmeta_buf == NULL) {
678     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
679     goto out;
680   }
681 
682   if (vbmeta_offset != 0) {
683     avb_debugv("Loading vbmeta struct in footer from partition '",
684                full_partition_name,
685                "'.\n",
686                NULL);
687   } else {
688     avb_debugv("Loading vbmeta struct from partition '",
689                full_partition_name,
690                "'.\n",
691                NULL);
692   }
693 
694   io_ret = ops->read_from_partition(ops,
695                                     full_partition_name,
696                                     vbmeta_offset,
697                                     vbmeta_size,
698                                     vbmeta_buf,
699                                     &vbmeta_num_read);
700   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
701     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
702     goto out;
703   } else if (io_ret != AVB_IO_RESULT_OK) {
704     /* If we're looking for 'vbmeta' but there is no such partition,
705      * go try to get it from the boot partition instead.
706      */
707     if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
708         !look_for_vbmeta_footer) {
709       avb_debugv(full_partition_name,
710                  ": No such partition. Trying 'boot' instead.\n",
711                  NULL);
712       ret = load_and_verify_vbmeta(ops,
713                                    requested_partitions,
714                                    ab_suffix,
715                                    flags,
716                                    allow_verification_error,
717                                    0 /* toplevel_vbmeta_flags */,
718                                    0 /* rollback_index_location */,
719                                    "boot",
720                                    avb_strlen("boot"),
721                                    NULL /* expected_public_key */,
722                                    0 /* expected_public_key_length */,
723                                    slot_data,
724                                    out_algorithm_type,
725                                    out_additional_cmdline_subst);
726       goto out;
727     } else {
728       avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
729       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
730       goto out;
731     }
732   }
733   avb_assert(vbmeta_num_read <= vbmeta_size);
734 
735   /* Check if the image is properly signed and get the public key used
736    * to sign the image.
737    */
738   vbmeta_ret =
739       avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
740   switch (vbmeta_ret) {
741     case AVB_VBMETA_VERIFY_RESULT_OK:
742       avb_assert(pk_data != NULL && pk_len > 0);
743       break;
744 
745     case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
746     case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
747     case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
748       ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
749       avb_errorv(full_partition_name,
750                  ": Error verifying vbmeta image: ",
751                  avb_vbmeta_verify_result_to_string(vbmeta_ret),
752                  "\n",
753                  NULL);
754       if (!allow_verification_error) {
755         goto out;
756       }
757       break;
758 
759     case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
760       /* No way to continue this case. */
761       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
762       avb_errorv(full_partition_name,
763                  ": Error verifying vbmeta image: invalid vbmeta header\n",
764                  NULL);
765       goto out;
766 
767     case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
768       /* No way to continue this case. */
769       ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
770       avb_errorv(full_partition_name,
771                  ": Error verifying vbmeta image: unsupported AVB version\n",
772                  NULL);
773       goto out;
774   }
775 
776   /* Byteswap the header. */
777   avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
778                                              &vbmeta_header);
779 
780   /* If we're the toplevel, assign flags so they'll be passed down. */
781   if (is_main_vbmeta) {
782     toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
783   } else {
784     if (vbmeta_header.flags != 0) {
785       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
786       avb_errorv(full_partition_name,
787                  ": chained vbmeta image has non-zero flags\n",
788                  NULL);
789       goto out;
790     }
791   }
792 
793   uint32_t rollback_index_location_to_use = rollback_index_location;
794 
795   /* Check if key used to make signature matches what is expected. */
796   if (pk_data != NULL) {
797     if (expected_public_key != NULL) {
798       avb_assert(!is_main_vbmeta);
799       if (expected_public_key_length != pk_len ||
800           avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
801         avb_errorv(full_partition_name,
802                    ": Public key used to sign data does not match key in chain "
803                    "partition descriptor.\n",
804                    NULL);
805         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
806         if (!allow_verification_error) {
807           goto out;
808         }
809       }
810     } else {
811       bool key_is_trusted = false;
812       const uint8_t* pk_metadata = NULL;
813       size_t pk_metadata_len = 0;
814 
815       if (vbmeta_header.public_key_metadata_size > 0) {
816         pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
817                       vbmeta_header.authentication_data_block_size +
818                       vbmeta_header.public_key_metadata_offset;
819         pk_metadata_len = vbmeta_header.public_key_metadata_size;
820       }
821 
822       // If we're not using a vbmeta partition, need to use another AvbOps...
823       if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
824         io_ret = ops->validate_public_key_for_partition(
825             ops,
826             full_partition_name,
827             pk_data,
828             pk_len,
829             pk_metadata,
830             pk_metadata_len,
831             &key_is_trusted,
832             &rollback_index_location_to_use);
833       } else {
834         avb_assert(is_main_vbmeta);
835         io_ret = ops->validate_vbmeta_public_key(ops,
836                                                  pk_data,
837                                                  pk_len,
838                                                  pk_metadata,
839                                                  pk_metadata_len,
840                                                  &key_is_trusted);
841       }
842 
843       if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
844         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
845         goto out;
846       } else if (io_ret != AVB_IO_RESULT_OK) {
847         avb_errorv(full_partition_name,
848                    ": Error while checking public key used to sign data.\n",
849                    NULL);
850         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
851         goto out;
852       }
853       if (!key_is_trusted) {
854         avb_errorv(full_partition_name,
855                    ": Public key used to sign data rejected.\n",
856                    NULL);
857         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
858         if (!allow_verification_error) {
859           goto out;
860         }
861       }
862     }
863   }
864 
865   /* Check rollback index. */
866   io_ret = ops->read_rollback_index(
867       ops, rollback_index_location_to_use, &stored_rollback_index);
868   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
869     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
870     goto out;
871   } else if (io_ret != AVB_IO_RESULT_OK) {
872     avb_errorv(full_partition_name,
873                ": Error getting rollback index for location.\n",
874                NULL);
875     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
876     goto out;
877   }
878   if (vbmeta_header.rollback_index < stored_rollback_index) {
879     avb_errorv(
880         full_partition_name,
881         ": Image rollback index is less than the stored rollback index.\n",
882         NULL);
883     ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
884     if (!allow_verification_error) {
885       goto out;
886     }
887   }
888 
889   /* Copy vbmeta to vbmeta_images before recursing. */
890   if (is_main_vbmeta) {
891     avb_assert(slot_data->num_vbmeta_images == 0);
892   } else {
893     if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
894       avb_assert(slot_data->num_vbmeta_images > 0);
895     }
896   }
897   if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
898     avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
899     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
900     goto out;
901   }
902   vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
903   vbmeta_image_data->partition_name = avb_strdup(partition_name);
904   vbmeta_image_data->vbmeta_data = vbmeta_buf;
905   /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
906    * and this includes data past the end of the image. Pass the
907    * actual size of the vbmeta image. Also, no need to use
908    * avb_safe_add() since the header has already been verified.
909    */
910   vbmeta_image_data->vbmeta_size =
911       sizeof(AvbVBMetaImageHeader) +
912       vbmeta_header.authentication_data_block_size +
913       vbmeta_header.auxiliary_data_block_size;
914   vbmeta_image_data->verify_result = vbmeta_ret;
915 
916   /* If verification has been disabled by setting a bit in the image,
917    * we're done... except that we need to load the entirety of the
918    * requested partitions.
919    */
920   if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
921     AvbSlotVerifyResult sub_ret;
922     avb_debugv(
923         full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
924     /* If load_requested_partitions() fail it is always a fatal
925      * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
926      * than recoverable (e.g. one where result_should_continue()
927      * returns true) and we want to convey that error.
928      */
929     sub_ret = load_requested_partitions(
930         ops, requested_partitions, ab_suffix, slot_data);
931     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
932       ret = sub_ret;
933     }
934     goto out;
935   }
936 
937   /* Now go through all descriptors and take the appropriate action:
938    *
939    * - hash descriptor: Load data from partition, calculate hash, and
940    *   checks that it matches what's in the hash descriptor.
941    *
942    * - hashtree descriptor: Do nothing since verification happens
943    *   on-the-fly from within the OS. (Unless the descriptor uses a
944    *   persistent digest, in which case we need to find it).
945    *
946    * - chained partition descriptor: Load the footer, load the vbmeta
947    *   image, verify vbmeta image (includes rollback checks, hash
948    *   checks, bail on chained partitions).
949    */
950   descriptors =
951       avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
952   for (n = 0; n < num_descriptors; n++) {
953     AvbDescriptor desc;
954 
955     if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
956       avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
957       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
958       goto out;
959     }
960 
961     switch (desc.tag) {
962       case AVB_DESCRIPTOR_TAG_HASH: {
963         AvbSlotVerifyResult sub_ret;
964         sub_ret = load_and_verify_hash_partition(ops,
965                                                  requested_partitions,
966                                                  ab_suffix,
967                                                  allow_verification_error,
968                                                  descriptors[n],
969                                                  slot_data);
970         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
971           ret = sub_ret;
972           if (!allow_verification_error || !result_should_continue(ret)) {
973             goto out;
974           }
975         }
976       } break;
977 
978       case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
979         AvbSlotVerifyResult sub_ret;
980         AvbChainPartitionDescriptor chain_desc;
981         const uint8_t* chain_partition_name;
982         const uint8_t* chain_public_key;
983 
984         /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
985         if (!is_main_vbmeta) {
986           avb_errorv(full_partition_name,
987                      ": Encountered chain descriptor not in main image.\n",
988                      NULL);
989           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
990           goto out;
991         }
992 
993         if (!avb_chain_partition_descriptor_validate_and_byteswap(
994                 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
995           avb_errorv(full_partition_name,
996                      ": Chain partition descriptor is invalid.\n",
997                      NULL);
998           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
999           goto out;
1000         }
1001 
1002         if (chain_desc.rollback_index_location == 0) {
1003           avb_errorv(full_partition_name,
1004                      ": Chain partition has invalid "
1005                      "rollback_index_location field.\n",
1006                      NULL);
1007           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1008           goto out;
1009         }
1010 
1011         chain_partition_name = ((const uint8_t*)descriptors[n]) +
1012                                sizeof(AvbChainPartitionDescriptor);
1013         chain_public_key = chain_partition_name + chain_desc.partition_name_len;
1014 
1015         sub_ret =
1016             load_and_verify_vbmeta(ops,
1017                                    requested_partitions,
1018                                    ab_suffix,
1019                                    flags,
1020                                    allow_verification_error,
1021                                    toplevel_vbmeta_flags,
1022                                    chain_desc.rollback_index_location,
1023                                    (const char*)chain_partition_name,
1024                                    chain_desc.partition_name_len,
1025                                    chain_public_key,
1026                                    chain_desc.public_key_len,
1027                                    slot_data,
1028                                    NULL, /* out_algorithm_type */
1029                                    NULL /* out_additional_cmdline_subst */);
1030         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1031           ret = sub_ret;
1032           if (!result_should_continue(ret)) {
1033             goto out;
1034           }
1035         }
1036       } break;
1037 
1038       case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
1039         const uint8_t* kernel_cmdline;
1040         AvbKernelCmdlineDescriptor kernel_cmdline_desc;
1041         bool apply_cmdline;
1042 
1043         if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
1044                 (AvbKernelCmdlineDescriptor*)descriptors[n],
1045                 &kernel_cmdline_desc)) {
1046           avb_errorv(full_partition_name,
1047                      ": Kernel cmdline descriptor is invalid.\n",
1048                      NULL);
1049           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1050           goto out;
1051         }
1052 
1053         kernel_cmdline = ((const uint8_t*)descriptors[n]) +
1054                          sizeof(AvbKernelCmdlineDescriptor);
1055 
1056         if (!avb_validate_utf8(kernel_cmdline,
1057                                kernel_cmdline_desc.kernel_cmdline_length)) {
1058           avb_errorv(full_partition_name,
1059                      ": Kernel cmdline is not valid UTF-8.\n",
1060                      NULL);
1061           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1062           goto out;
1063         }
1064 
1065         /* Compare the flags for top-level VBMeta struct with flags in
1066          * the command-line descriptor so command-line snippets only
1067          * intended for a certain mode (dm-verity enabled/disabled)
1068          * are skipped if applicable.
1069          */
1070         apply_cmdline = true;
1071         if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1072           if (kernel_cmdline_desc.flags &
1073               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
1074             apply_cmdline = false;
1075           }
1076         } else {
1077           if (kernel_cmdline_desc.flags &
1078               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
1079             apply_cmdline = false;
1080           }
1081         }
1082 
1083         if (apply_cmdline) {
1084           if (slot_data->cmdline == NULL) {
1085             slot_data->cmdline =
1086                 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
1087             if (slot_data->cmdline == NULL) {
1088               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1089               goto out;
1090             }
1091             avb_memcpy(slot_data->cmdline,
1092                        kernel_cmdline,
1093                        kernel_cmdline_desc.kernel_cmdline_length);
1094           } else {
1095             /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
1096             size_t orig_size = avb_strlen(slot_data->cmdline);
1097             size_t new_size =
1098                 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
1099             char* new_cmdline = avb_calloc(new_size);
1100             if (new_cmdline == NULL) {
1101               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1102               goto out;
1103             }
1104             avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
1105             new_cmdline[orig_size] = ' ';
1106             avb_memcpy(new_cmdline + orig_size + 1,
1107                        kernel_cmdline,
1108                        kernel_cmdline_desc.kernel_cmdline_length);
1109             avb_free(slot_data->cmdline);
1110             slot_data->cmdline = new_cmdline;
1111           }
1112         }
1113       } break;
1114 
1115       case AVB_DESCRIPTOR_TAG_HASHTREE: {
1116         AvbHashtreeDescriptor hashtree_desc;
1117 
1118         if (!avb_hashtree_descriptor_validate_and_byteswap(
1119                 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
1120           avb_errorv(
1121               full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
1122           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1123           goto out;
1124         }
1125 
1126         /* We only need to continue when there is no digest in the descriptor.
1127          * This is because the only processing here is to find the digest and
1128          * make it available on the kernel command line.
1129          */
1130         if (hashtree_desc.root_digest_len == 0) {
1131           char part_name[AVB_PART_NAME_MAX_SIZE];
1132           size_t digest_len = 0;
1133           uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
1134           const uint8_t* desc_partition_name =
1135               ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
1136 
1137           if (!avb_validate_utf8(desc_partition_name,
1138                                  hashtree_desc.partition_name_len)) {
1139             avb_error("Partition name is not valid UTF-8.\n");
1140             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1141             goto out;
1142           }
1143 
1144           /* No ab_suffix for partitions without a digest in the descriptor
1145            * because these partitions hold data unique to this device and are
1146            * not updated using an A/B scheme.
1147            */
1148           if ((hashtree_desc.flags &
1149                AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
1150               avb_strlen(ab_suffix) != 0) {
1151             avb_error("Cannot use A/B with a persistent root digest.\n");
1152             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1153             goto out;
1154           }
1155           if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
1156             avb_error("Partition name does not fit.\n");
1157             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1158             goto out;
1159           }
1160           avb_memcpy(
1161               part_name, desc_partition_name, hashtree_desc.partition_name_len);
1162           part_name[hashtree_desc.partition_name_len] = '\0';
1163 
1164           /* Determine the expected digest size from the hash algorithm. */
1165           if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1166               0) {
1167             digest_len = AVB_SHA1_DIGEST_SIZE;
1168           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1169                                 "sha256") == 0) {
1170             digest_len = AVB_SHA256_DIGEST_SIZE;
1171           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1172                                 "sha512") == 0) {
1173             digest_len = AVB_SHA512_DIGEST_SIZE;
1174           } else {
1175             avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1176             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1177             goto out;
1178           }
1179 
1180           ret = read_persistent_digest(ops,
1181                                        part_name,
1182                                        digest_len,
1183                                        NULL /* initial_digest */,
1184                                        digest_buf);
1185           if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1186             goto out;
1187           }
1188 
1189           if (out_additional_cmdline_subst) {
1190             ret =
1191                 avb_add_root_digest_substitution(part_name,
1192                                                  digest_buf,
1193                                                  digest_len,
1194                                                  out_additional_cmdline_subst);
1195             if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1196               goto out;
1197             }
1198           }
1199         }
1200       } break;
1201 
1202       case AVB_DESCRIPTOR_TAG_PROPERTY:
1203         /* Do nothing. */
1204         break;
1205     }
1206   }
1207 
1208   if (rollback_index_location < 0 ||
1209       rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1210     avb_errorv(
1211         full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1212     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1213     goto out;
1214   }
1215 
1216   slot_data->rollback_indexes[rollback_index_location] =
1217       vbmeta_header.rollback_index;
1218 
1219   if (out_algorithm_type != NULL) {
1220     *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1221   }
1222 
1223 out:
1224   /* If |vbmeta_image_data| isn't NULL it means that it adopted
1225    * |vbmeta_buf| so in that case don't free it here.
1226    */
1227   if (vbmeta_image_data == NULL) {
1228     if (vbmeta_buf != NULL) {
1229       avb_free(vbmeta_buf);
1230     }
1231   }
1232   if (descriptors != NULL) {
1233     avb_free(descriptors);
1234   }
1235   return ret;
1236 }
1237 
avb_manage_hashtree_error_mode(AvbOps * ops,AvbSlotVerifyFlags flags,AvbSlotVerifyData * data,AvbHashtreeErrorMode * out_hashtree_error_mode)1238 static AvbIOResult avb_manage_hashtree_error_mode(
1239     AvbOps* ops,
1240     AvbSlotVerifyFlags flags,
1241     AvbSlotVerifyData* data,
1242     AvbHashtreeErrorMode* out_hashtree_error_mode) {
1243   AvbHashtreeErrorMode ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1244   AvbIOResult io_ret = AVB_IO_RESULT_OK;
1245   uint8_t vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1246   uint8_t stored_vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1247   size_t num_bytes_read;
1248 
1249   avb_assert(out_hashtree_error_mode != NULL);
1250   avb_assert(ops->read_persistent_value != NULL);
1251   avb_assert(ops->write_persistent_value != NULL);
1252 
1253   // If we're rebooting because of dm-verity corruption, make a note of
1254   // the vbmeta hash so we can stay in 'eio' mode until things change.
1255   if (flags & AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION) {
1256     avb_debug(
1257         "Rebooting because of dm-verity corruption - "
1258         "recording OS instance and using 'eio' mode.\n");
1259     avb_slot_verify_data_calculate_vbmeta_digest(
1260         data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1261     io_ret = ops->write_persistent_value(ops,
1262                                          AVB_NPV_MANAGED_VERITY_MODE,
1263                                          AVB_SHA256_DIGEST_SIZE,
1264                                          vbmeta_digest_sha256);
1265     if (io_ret != AVB_IO_RESULT_OK) {
1266       avb_error("Error writing to " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1267       goto out;
1268     }
1269     ret = AVB_HASHTREE_ERROR_MODE_EIO;
1270     io_ret = AVB_IO_RESULT_OK;
1271     goto out;
1272   }
1273 
1274   // See if we're in 'eio' mode.
1275   io_ret = ops->read_persistent_value(ops,
1276                                       AVB_NPV_MANAGED_VERITY_MODE,
1277                                       AVB_SHA256_DIGEST_SIZE,
1278                                       stored_vbmeta_digest_sha256,
1279                                       &num_bytes_read);
1280   if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE ||
1281       (io_ret == AVB_IO_RESULT_OK && num_bytes_read == 0)) {
1282     // This is the usual case ('eio' mode not set).
1283     avb_debug("No dm-verity corruption - using in 'restart' mode.\n");
1284     ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1285     io_ret = AVB_IO_RESULT_OK;
1286     goto out;
1287   } else if (io_ret != AVB_IO_RESULT_OK) {
1288     avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1289     goto out;
1290   }
1291   if (num_bytes_read != AVB_SHA256_DIGEST_SIZE) {
1292     avb_error(
1293         "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
1294         ".\n");
1295     io_ret = AVB_IO_RESULT_ERROR_IO;
1296     goto out;
1297   }
1298 
1299   // OK, so we're currently in 'eio' mode and the vbmeta digest of the OS
1300   // that caused this is in |stored_vbmeta_digest_sha256| ... now see if
1301   // the OS we're dealing with now is the same.
1302   avb_slot_verify_data_calculate_vbmeta_digest(
1303       data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1304   if (avb_memcmp(vbmeta_digest_sha256,
1305                  stored_vbmeta_digest_sha256,
1306                  AVB_SHA256_DIGEST_SIZE) == 0) {
1307     // It's the same so we're still in 'eio' mode.
1308     avb_debug("Same OS instance detected - staying in 'eio' mode.\n");
1309     ret = AVB_HASHTREE_ERROR_MODE_EIO;
1310     io_ret = AVB_IO_RESULT_OK;
1311   } else {
1312     // It did change!
1313     avb_debug(
1314         "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
1315     io_ret =
1316         ops->write_persistent_value(ops,
1317                                     AVB_NPV_MANAGED_VERITY_MODE,
1318                                     0,  // This clears the persistent property.
1319                                     vbmeta_digest_sha256);
1320     if (io_ret != AVB_IO_RESULT_OK) {
1321       avb_error("Error clearing " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1322       goto out;
1323     }
1324     ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1325     io_ret = AVB_IO_RESULT_OK;
1326   }
1327 
1328 out:
1329   *out_hashtree_error_mode = ret;
1330   return io_ret;
1331 }
1332 
has_system_partition(AvbOps * ops,const char * ab_suffix)1333 static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
1334   char part_name[AVB_PART_NAME_MAX_SIZE];
1335   char* system_part_name = "system";
1336   char guid_buf[37];
1337   AvbIOResult io_ret;
1338 
1339   if (!avb_str_concat(part_name,
1340                       sizeof part_name,
1341                       system_part_name,
1342                       avb_strlen(system_part_name),
1343                       ab_suffix,
1344                       avb_strlen(ab_suffix))) {
1345     avb_error("System partition name and suffix does not fit.\n");
1346     return false;
1347   }
1348 
1349   io_ret = ops->get_unique_guid_for_partition(
1350       ops, part_name, guid_buf, sizeof guid_buf);
1351   if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
1352     avb_debug("No system partition.\n");
1353     return false;
1354   } else if (io_ret != AVB_IO_RESULT_OK) {
1355     avb_error("Error getting unique GUID for system partition.\n");
1356     return false;
1357   }
1358 
1359   return true;
1360 }
1361 
avb_slot_verify(AvbOps * ops,const char * const * requested_partitions,const char * ab_suffix,AvbSlotVerifyFlags flags,AvbHashtreeErrorMode hashtree_error_mode,AvbSlotVerifyData ** out_data)1362 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1363                                     const char* const* requested_partitions,
1364                                     const char* ab_suffix,
1365                                     AvbSlotVerifyFlags flags,
1366                                     AvbHashtreeErrorMode hashtree_error_mode,
1367                                     AvbSlotVerifyData** out_data) {
1368   AvbSlotVerifyResult ret;
1369   AvbSlotVerifyData* slot_data = NULL;
1370   AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1371   bool using_boot_for_vbmeta = false;
1372   AvbVBMetaImageHeader toplevel_vbmeta;
1373   bool allow_verification_error =
1374       (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1375   AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1376 
1377   /* Fail early if we're missing the AvbOps needed for slot verification. */
1378   avb_assert(ops->read_is_device_unlocked != NULL);
1379   avb_assert(ops->read_from_partition != NULL);
1380   avb_assert(ops->get_size_of_partition != NULL);
1381   avb_assert(ops->read_rollback_index != NULL);
1382   avb_assert(ops->get_unique_guid_for_partition != NULL);
1383 
1384   if (out_data != NULL) {
1385     *out_data = NULL;
1386   }
1387 
1388   /* Allowing dm-verity errors defeats the purpose of verified boot so
1389    * only allow this if set up to allow verification errors
1390    * (e.g. typically only UNLOCKED mode).
1391    */
1392   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1393       !allow_verification_error) {
1394     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1395     goto fail;
1396   }
1397 
1398   /* Make sure passed-in AvbOps support persistent values if
1399    * asking for libavb to manage verity state.
1400    */
1401   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1402     if (ops->read_persistent_value == NULL ||
1403         ops->write_persistent_value == NULL) {
1404       avb_error(
1405           "Persistent values required for "
1406           "AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO "
1407           "but are not implemented in given AvbOps.\n");
1408       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1409       goto fail;
1410     }
1411   }
1412 
1413   /* Make sure passed-in AvbOps support verifying public keys and getting
1414    * rollback index location if not using a vbmeta partition.
1415    */
1416   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1417     if (ops->validate_public_key_for_partition == NULL) {
1418       avb_error(
1419           "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
1420           "validate_public_key_for_partition() operation isn't implemented.\n");
1421       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1422       goto fail;
1423     }
1424   } else {
1425     avb_assert(ops->validate_vbmeta_public_key != NULL);
1426   }
1427 
1428   slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1429   if (slot_data == NULL) {
1430     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1431     goto fail;
1432   }
1433   slot_data->vbmeta_images =
1434       avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1435   if (slot_data->vbmeta_images == NULL) {
1436     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1437     goto fail;
1438   }
1439   slot_data->loaded_partitions =
1440       avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1441   if (slot_data->loaded_partitions == NULL) {
1442     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1443     goto fail;
1444   }
1445 
1446   additional_cmdline_subst = avb_new_cmdline_subst_list();
1447   if (additional_cmdline_subst == NULL) {
1448     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1449     goto fail;
1450   }
1451 
1452   if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1453     if (requested_partitions == NULL || requested_partitions[0] == NULL) {
1454       avb_fatal(
1455           "Requested partitions cannot be empty when using "
1456           "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
1457       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1458       goto fail;
1459     }
1460 
1461     /* No vbmeta partition, go through each of the requested partitions... */
1462     for (size_t n = 0; requested_partitions[n] != NULL; n++) {
1463       ret = load_and_verify_vbmeta(ops,
1464                                    requested_partitions,
1465                                    ab_suffix,
1466                                    flags,
1467                                    allow_verification_error,
1468                                    0 /* toplevel_vbmeta_flags */,
1469                                    0 /* rollback_index_location */,
1470                                    requested_partitions[n],
1471                                    avb_strlen(requested_partitions[n]),
1472                                    NULL /* expected_public_key */,
1473                                    0 /* expected_public_key_length */,
1474                                    slot_data,
1475                                    &algorithm_type,
1476                                    additional_cmdline_subst);
1477       if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1478         goto fail;
1479       }
1480     }
1481 
1482   } else {
1483     /* Usual path, load "vbmeta"... */
1484     ret = load_and_verify_vbmeta(ops,
1485                                  requested_partitions,
1486                                  ab_suffix,
1487                                  flags,
1488                                  allow_verification_error,
1489                                  0 /* toplevel_vbmeta_flags */,
1490                                  0 /* rollback_index_location */,
1491                                  "vbmeta",
1492                                  avb_strlen("vbmeta"),
1493                                  NULL /* expected_public_key */,
1494                                  0 /* expected_public_key_length */,
1495                                  slot_data,
1496                                  &algorithm_type,
1497                                  additional_cmdline_subst);
1498     if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1499       goto fail;
1500     }
1501   }
1502 
1503   if (!result_should_continue(ret)) {
1504     goto fail;
1505   }
1506 
1507   /* If things check out, mangle the kernel command-line as needed. */
1508   if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
1509     if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1510       avb_assert(
1511           avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1512       using_boot_for_vbmeta = true;
1513     }
1514   }
1515 
1516   /* Byteswap top-level vbmeta header since we'll need it below. */
1517   avb_vbmeta_image_header_to_host_byte_order(
1518       (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1519       &toplevel_vbmeta);
1520 
1521   /* Fill in |ab_suffix| field. */
1522   slot_data->ab_suffix = avb_strdup(ab_suffix);
1523   if (slot_data->ab_suffix == NULL) {
1524     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1525     goto fail;
1526   }
1527 
1528   /* If verification is disabled, we are done ... we specifically
1529    * don't want to add any androidboot.* options since verification
1530    * is disabled.
1531    */
1532   if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1533     /* Since verification is disabled we didn't process any
1534      * descriptors and thus there's no cmdline... so set root= such
1535      * that the system partition is mounted.
1536      */
1537     avb_assert(slot_data->cmdline == NULL);
1538     // Devices with dynamic partitions won't have system partition.
1539     // Instead, it has a large super partition to accommodate *.img files.
1540     // See b/119551429 for details.
1541     if (has_system_partition(ops, ab_suffix)) {
1542       slot_data->cmdline =
1543           avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1544     } else {
1545       // The |cmdline| field should be a NUL-terminated string.
1546       slot_data->cmdline = avb_strdup("");
1547     }
1548     if (slot_data->cmdline == NULL) {
1549       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1550       goto fail;
1551     }
1552   } else {
1553     /* If requested, manage dm-verity mode... */
1554     AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
1555     if (hashtree_error_mode ==
1556         AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1557       AvbIOResult io_ret;
1558       io_ret = avb_manage_hashtree_error_mode(
1559           ops, flags, slot_data, &resolved_hashtree_error_mode);
1560       if (io_ret != AVB_IO_RESULT_OK) {
1561         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1562         if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1563           ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1564         }
1565         goto fail;
1566       }
1567     }
1568     slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
1569 
1570     /* Add options... */
1571     AvbSlotVerifyResult sub_ret;
1572     sub_ret = avb_append_options(ops,
1573                                  flags,
1574                                  slot_data,
1575                                  &toplevel_vbmeta,
1576                                  algorithm_type,
1577                                  hashtree_error_mode,
1578                                  resolved_hashtree_error_mode);
1579     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1580       ret = sub_ret;
1581       goto fail;
1582     }
1583   }
1584 
1585   /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1586   if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
1587     char* new_cmdline;
1588     new_cmdline = avb_sub_cmdline(ops,
1589                                   slot_data->cmdline,
1590                                   ab_suffix,
1591                                   using_boot_for_vbmeta,
1592                                   additional_cmdline_subst);
1593     if (new_cmdline != slot_data->cmdline) {
1594       if (new_cmdline == NULL) {
1595         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1596         goto fail;
1597       }
1598       avb_free(slot_data->cmdline);
1599       slot_data->cmdline = new_cmdline;
1600     }
1601   }
1602 
1603   if (out_data != NULL) {
1604     *out_data = slot_data;
1605   } else {
1606     avb_slot_verify_data_free(slot_data);
1607   }
1608 
1609   avb_free_cmdline_subst_list(additional_cmdline_subst);
1610   additional_cmdline_subst = NULL;
1611 
1612   if (!allow_verification_error) {
1613     avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1614   }
1615 
1616   return ret;
1617 
1618 fail:
1619   if (slot_data != NULL) {
1620     avb_slot_verify_data_free(slot_data);
1621   }
1622   if (additional_cmdline_subst != NULL) {
1623     avb_free_cmdline_subst_list(additional_cmdline_subst);
1624   }
1625   return ret;
1626 }
1627 
avb_slot_verify_data_free(AvbSlotVerifyData * data)1628 void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1629   if (data->ab_suffix != NULL) {
1630     avb_free(data->ab_suffix);
1631   }
1632   if (data->cmdline != NULL) {
1633     avb_free(data->cmdline);
1634   }
1635   if (data->vbmeta_images != NULL) {
1636     size_t n;
1637     for (n = 0; n < data->num_vbmeta_images; n++) {
1638       AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1639       if (vbmeta_image->partition_name != NULL) {
1640         avb_free(vbmeta_image->partition_name);
1641       }
1642       if (vbmeta_image->vbmeta_data != NULL) {
1643         avb_free(vbmeta_image->vbmeta_data);
1644       }
1645     }
1646     avb_free(data->vbmeta_images);
1647   }
1648   if (data->loaded_partitions != NULL) {
1649     size_t n;
1650     for (n = 0; n < data->num_loaded_partitions; n++) {
1651       AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1652       if (loaded_partition->partition_name != NULL) {
1653         avb_free(loaded_partition->partition_name);
1654       }
1655       if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1656         avb_free(loaded_partition->data);
1657       }
1658     }
1659     avb_free(data->loaded_partitions);
1660   }
1661   avb_free(data);
1662 }
1663 
avb_slot_verify_result_to_string(AvbSlotVerifyResult result)1664 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1665   const char* ret = NULL;
1666 
1667   switch (result) {
1668     case AVB_SLOT_VERIFY_RESULT_OK:
1669       ret = "OK";
1670       break;
1671     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1672       ret = "ERROR_OOM";
1673       break;
1674     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1675       ret = "ERROR_IO";
1676       break;
1677     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1678       ret = "ERROR_VERIFICATION";
1679       break;
1680     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1681       ret = "ERROR_ROLLBACK_INDEX";
1682       break;
1683     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1684       ret = "ERROR_PUBLIC_KEY_REJECTED";
1685       break;
1686     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1687       ret = "ERROR_INVALID_METADATA";
1688       break;
1689     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1690       ret = "ERROR_UNSUPPORTED_VERSION";
1691       break;
1692     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1693       ret = "ERROR_INVALID_ARGUMENT";
1694       break;
1695       /* Do not add a 'default:' case here because of -Wswitch. */
1696   }
1697 
1698   if (ret == NULL) {
1699     avb_error("Unknown AvbSlotVerifyResult value.\n");
1700     ret = "(unknown)";
1701   }
1702 
1703   return ret;
1704 }
1705 
avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData * data,AvbDigestType digest_type,uint8_t * out_digest)1706 void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
1707                                                   AvbDigestType digest_type,
1708                                                   uint8_t* out_digest) {
1709   bool ret = false;
1710   size_t n;
1711 
1712   switch (digest_type) {
1713     case AVB_DIGEST_TYPE_SHA256: {
1714       AvbSHA256Ctx ctx;
1715       avb_sha256_init(&ctx);
1716       for (n = 0; n < data->num_vbmeta_images; n++) {
1717         avb_sha256_update(&ctx,
1718                           data->vbmeta_images[n].vbmeta_data,
1719                           data->vbmeta_images[n].vbmeta_size);
1720       }
1721       avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
1722       ret = true;
1723     } break;
1724 
1725     case AVB_DIGEST_TYPE_SHA512: {
1726       AvbSHA512Ctx ctx;
1727       avb_sha512_init(&ctx);
1728       for (n = 0; n < data->num_vbmeta_images; n++) {
1729         avb_sha512_update(&ctx,
1730                           data->vbmeta_images[n].vbmeta_data,
1731                           data->vbmeta_images[n].vbmeta_size);
1732       }
1733       avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
1734       ret = true;
1735     } break;
1736 
1737       /* Do not add a 'default:' case here because of -Wswitch. */
1738   }
1739 
1740   if (!ret) {
1741     avb_fatal("Unknown digest type");
1742   }
1743 }
1744