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