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