]> git.sur5r.net Git - u-boot/blob - lib/libavb/avb_property_descriptor.c
2627cd0d64f4a9e9e8e797e33fb7c99072e8b7ec
[u-boot] / lib / libavb / avb_property_descriptor.c
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * SPDX-License-Identifier:     MIT
5  */
6
7 #include "avb_property_descriptor.h"
8 #include "avb_util.h"
9
10 bool avb_property_descriptor_validate_and_byteswap(
11     const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
12   uint64_t expected_size;
13
14   avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
15
16   if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
17                                             (AvbDescriptor*)dest))
18     return false;
19
20   if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
21     avb_error("Invalid tag for property descriptor.\n");
22     return false;
23   }
24
25   dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
26   dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
27
28   /* Check that key and value are fully contained. */
29   expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
30   if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
31       !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
32     avb_error("Overflow while adding up sizes.\n");
33     return false;
34   }
35   if (expected_size > dest->parent_descriptor.num_bytes_following) {
36     avb_error("Descriptor payload size overflow.\n");
37     return false;
38   }
39
40   return true;
41 }
42
43 typedef struct {
44   const char* key;
45   size_t key_size;
46   const char* ret_value;
47   size_t ret_value_size;
48 } PropertyIteratorData;
49
50 static bool property_lookup_desc_foreach(const AvbDescriptor* header,
51                                          void* user_data) {
52   PropertyIteratorData* data = (PropertyIteratorData*)user_data;
53   AvbPropertyDescriptor prop_desc;
54   const uint8_t* p;
55   bool ret = true;
56
57   if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
58     goto out;
59   }
60
61   if (!avb_property_descriptor_validate_and_byteswap(
62           (const AvbPropertyDescriptor*)header, &prop_desc)) {
63     goto out;
64   }
65
66   p = (const uint8_t*)header;
67   if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
68     avb_error("No terminating NUL byte in key.\n");
69     goto out;
70   }
71
72   if (data->key_size == prop_desc.key_num_bytes) {
73     if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
74                    data->key,
75                    data->key_size) == 0) {
76       data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
77                                       prop_desc.key_num_bytes + 1);
78       data->ret_value_size = prop_desc.value_num_bytes;
79       /* Stop iterating. */
80       ret = false;
81       goto out;
82     }
83   }
84
85 out:
86   return ret;
87 }
88
89 const char* avb_property_lookup(const uint8_t* image_data,
90                                 size_t image_size,
91                                 const char* key,
92                                 size_t key_size,
93                                 size_t* out_value_size) {
94   PropertyIteratorData data;
95
96   if (key_size == 0) {
97     key_size = avb_strlen(key);
98   }
99
100   data.key = key;
101   data.key_size = key_size;
102
103   if (avb_descriptor_foreach(
104           image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
105     if (out_value_size != NULL) {
106       *out_value_size = data.ret_value_size;
107     }
108     return data.ret_value;
109   }
110
111   if (out_value_size != NULL) {
112     *out_value_size = 0;
113   }
114   return NULL;
115 }
116
117 bool avb_property_lookup_uint64(const uint8_t* image_data,
118                                 size_t image_size,
119                                 const char* key,
120                                 size_t key_size,
121                                 uint64_t* out_value) {
122   const char* value;
123   bool ret = false;
124   uint64_t parsed_val;
125   int base;
126   int n;
127
128   value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
129   if (value == NULL) {
130     goto out;
131   }
132
133   base = 10;
134   if (avb_memcmp(value, "0x", 2) == 0) {
135     base = 16;
136     value += 2;
137   }
138
139   parsed_val = 0;
140   for (n = 0; value[n] != '\0'; n++) {
141     int c = value[n];
142     int digit;
143
144     parsed_val *= base;
145
146     if (c >= '0' && c <= '9') {
147       digit = c - '0';
148     } else if (base == 16 && c >= 'a' && c <= 'f') {
149       digit = c - 'a' + 10;
150     } else if (base == 16 && c >= 'A' && c <= 'F') {
151       digit = c - 'A' + 10;
152     } else {
153       avb_error("Invalid digit.\n");
154       goto out;
155     }
156
157     parsed_val += digit;
158   }
159
160   ret = true;
161   if (out_value != NULL) {
162     *out_value = parsed_val;
163   }
164
165 out:
166   return ret;
167 }