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