Home | History | Annotate | Download | only in libavb
      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_descriptor.h"
     26 #include "avb_util.h"
     27 #include "avb_vbmeta_image.h"
     28 
     29 bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
     30                                           AvbDescriptor* dest) {
     31   dest->tag = avb_be64toh(src->tag);
     32   dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
     33 
     34   if ((dest->num_bytes_following & 0x07) != 0) {
     35     avb_error("Descriptor size is not divisible by 8.\n");
     36     return false;
     37   }
     38   return true;
     39 }
     40 
     41 bool avb_descriptor_foreach(const uint8_t* image_data,
     42                             size_t image_size,
     43                             AvbDescriptorForeachFunc foreach_func,
     44                             void* user_data) {
     45   const AvbVBMetaImageHeader* header = NULL;
     46   bool ret = false;
     47   const uint8_t* image_end;
     48   const uint8_t* desc_start;
     49   const uint8_t* desc_end;
     50   const uint8_t* p;
     51 
     52   if (image_data == NULL) {
     53     avb_error("image_data is NULL\n.");
     54     goto out;
     55   }
     56 
     57   if (foreach_func == NULL) {
     58     avb_error("foreach_func is NULL\n.");
     59     goto out;
     60   }
     61 
     62   if (image_size < sizeof(AvbVBMetaImageHeader)) {
     63     avb_error("Length is smaller than header.\n");
     64     goto out;
     65   }
     66 
     67   /* Ensure magic is correct. */
     68   if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
     69     avb_error("Magic is incorrect.\n");
     70     goto out;
     71   }
     72 
     73   /* Careful, not byteswapped - also ensure it's aligned properly. */
     74   avb_assert_aligned(image_data);
     75   header = (const AvbVBMetaImageHeader*)image_data;
     76   image_end = image_data + image_size;
     77 
     78   desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
     79                avb_be64toh(header->authentication_data_block_size) +
     80                avb_be64toh(header->descriptors_offset);
     81 
     82   desc_end = desc_start + avb_be64toh(header->descriptors_size);
     83 
     84   if (desc_start < image_data || desc_start > image_end ||
     85       desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
     86     avb_error("Descriptors not inside passed-in data.\n");
     87     goto out;
     88   }
     89 
     90   for (p = desc_start; p < desc_end;) {
     91     const AvbDescriptor* dh = (const AvbDescriptor*)p;
     92     avb_assert_aligned(dh);
     93     uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
     94     uint64_t nb_total = sizeof(AvbDescriptor) + nb_following;
     95 
     96     if ((nb_total & 7) != 0) {
     97       avb_error("Invalid descriptor length.\n");
     98       goto out;
     99     }
    100 
    101     if (nb_total + p < desc_start || nb_total + p > desc_end) {
    102       avb_error("Invalid data in descriptors array.\n");
    103       goto out;
    104     }
    105 
    106     if (foreach_func(dh, user_data) == 0) {
    107       goto out;
    108     }
    109 
    110     p += nb_total;
    111   }
    112 
    113   ret = true;
    114 
    115 out:
    116   return ret;
    117 }
    118 
    119 static bool count_descriptors(const AvbDescriptor* descriptor,
    120                               void* user_data) {
    121   size_t* num_descriptors = user_data;
    122   *num_descriptors += 1;
    123   return true;
    124 }
    125 
    126 typedef struct {
    127   size_t descriptor_number;
    128   const AvbDescriptor** descriptors;
    129 } SetDescriptorData;
    130 
    131 static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
    132   SetDescriptorData* data = user_data;
    133   data->descriptors[data->descriptor_number++] = descriptor;
    134   return true;
    135 }
    136 
    137 const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
    138                                              size_t image_size,
    139                                              size_t* out_num_descriptors) {
    140   size_t num_descriptors = 0;
    141   SetDescriptorData data;
    142 
    143   avb_descriptor_foreach(
    144       image_data, image_size, count_descriptors, &num_descriptors);
    145 
    146   data.descriptor_number = 0;
    147   data.descriptors =
    148       avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
    149   if (data.descriptors == NULL) {
    150     return NULL;
    151   }
    152   avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
    153   avb_assert(data.descriptor_number == num_descriptors);
    154 
    155   if (out_num_descriptors != NULL) {
    156     *out_num_descriptors = num_descriptors;
    157   }
    158 
    159   return data.descriptors;
    160 }
    161