1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright (C) 2016 The Android Open Source Project 4 */ 5 6 #include "avb_descriptor.h" 7 #include "avb_util.h" 8 #include "avb_vbmeta_image.h" 9 10 bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src, 11 AvbDescriptor* dest) { 12 dest->tag = avb_be64toh(src->tag); 13 dest->num_bytes_following = avb_be64toh(src->num_bytes_following); 14 15 if ((dest->num_bytes_following & 0x07) != 0) { 16 avb_error("Descriptor size is not divisible by 8.\n"); 17 return false; 18 } 19 return true; 20 } 21 22 bool avb_descriptor_foreach(const uint8_t* image_data, 23 size_t image_size, 24 AvbDescriptorForeachFunc foreach_func, 25 void* user_data) { 26 const AvbVBMetaImageHeader* header = NULL; 27 bool ret = false; 28 const uint8_t* image_end; 29 const uint8_t* desc_start; 30 const uint8_t* desc_end; 31 const uint8_t* p; 32 33 if (image_data == NULL) { 34 avb_error("image_data is NULL\n."); 35 goto out; 36 } 37 38 if (foreach_func == NULL) { 39 avb_error("foreach_func is NULL\n."); 40 goto out; 41 } 42 43 if (image_size < sizeof(AvbVBMetaImageHeader)) { 44 avb_error("Length is smaller than header.\n"); 45 goto out; 46 } 47 48 /* Ensure magic is correct. */ 49 if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) { 50 avb_error("Magic is incorrect.\n"); 51 goto out; 52 } 53 54 /* Careful, not byteswapped - also ensure it's aligned properly. */ 55 avb_assert_aligned(image_data); 56 header = (const AvbVBMetaImageHeader*)image_data; 57 image_end = image_data + image_size; 58 59 desc_start = image_data + sizeof(AvbVBMetaImageHeader) + 60 avb_be64toh(header->authentication_data_block_size) + 61 avb_be64toh(header->descriptors_offset); 62 63 desc_end = desc_start + avb_be64toh(header->descriptors_size); 64 65 if (desc_start < image_data || desc_start > image_end || 66 desc_end < image_data || desc_end > image_end || desc_end < desc_start) { 67 avb_error("Descriptors not inside passed-in data.\n"); 68 goto out; 69 } 70 71 for (p = desc_start; p < desc_end;) { 72 const AvbDescriptor* dh = (const AvbDescriptor*)p; 73 avb_assert_aligned(dh); 74 uint64_t nb_following = avb_be64toh(dh->num_bytes_following); 75 uint64_t nb_total = sizeof(AvbDescriptor) + nb_following; 76 77 if ((nb_total & 7) != 0) { 78 avb_error("Invalid descriptor length.\n"); 79 goto out; 80 } 81 82 if (nb_total + p < desc_start || nb_total + p > desc_end) { 83 avb_error("Invalid data in descriptors array.\n"); 84 goto out; 85 } 86 87 if (foreach_func(dh, user_data) == 0) { 88 goto out; 89 } 90 91 p += nb_total; 92 } 93 94 ret = true; 95 96 out: 97 return ret; 98 } 99 100 static bool count_descriptors(const AvbDescriptor* descriptor, 101 void* user_data) { 102 size_t* num_descriptors = user_data; 103 *num_descriptors += 1; 104 return true; 105 } 106 107 typedef struct { 108 size_t descriptor_number; 109 const AvbDescriptor** descriptors; 110 } SetDescriptorData; 111 112 static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) { 113 SetDescriptorData* data = user_data; 114 data->descriptors[data->descriptor_number++] = descriptor; 115 return true; 116 } 117 118 const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data, 119 size_t image_size, 120 size_t* out_num_descriptors) { 121 size_t num_descriptors = 0; 122 SetDescriptorData data; 123 124 avb_descriptor_foreach( 125 image_data, image_size, count_descriptors, &num_descriptors); 126 127 data.descriptor_number = 0; 128 data.descriptors = 129 avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1)); 130 if (data.descriptors == NULL) { 131 return NULL; 132 } 133 avb_descriptor_foreach(image_data, image_size, set_descriptors, &data); 134 avb_assert(data.descriptor_number == num_descriptors); 135 136 if (out_num_descriptors != NULL) { 137 *out_num_descriptors = num_descriptors; 138 } 139 140 return data.descriptors; 141 } 142