xref: /openbmc/u-boot/lib/libavb/avb_util.c (revision 1a68faac)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright (C) 2016 The Android Open Source Project
4  */
5 
6 #include "avb_util.h"
7 
8 #include <stdarg.h>
9 
10 uint32_t avb_be32toh(uint32_t in) {
11   uint8_t* d = (uint8_t*)&in;
12   uint32_t ret;
13   ret = ((uint32_t)d[0]) << 24;
14   ret |= ((uint32_t)d[1]) << 16;
15   ret |= ((uint32_t)d[2]) << 8;
16   ret |= ((uint32_t)d[3]);
17   return ret;
18 }
19 
20 uint64_t avb_be64toh(uint64_t in) {
21   uint8_t* d = (uint8_t*)&in;
22   uint64_t ret;
23   ret = ((uint64_t)d[0]) << 56;
24   ret |= ((uint64_t)d[1]) << 48;
25   ret |= ((uint64_t)d[2]) << 40;
26   ret |= ((uint64_t)d[3]) << 32;
27   ret |= ((uint64_t)d[4]) << 24;
28   ret |= ((uint64_t)d[5]) << 16;
29   ret |= ((uint64_t)d[6]) << 8;
30   ret |= ((uint64_t)d[7]);
31   return ret;
32 }
33 
34 /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
35 uint32_t avb_htobe32(uint32_t in) {
36   union {
37     uint32_t word;
38     uint8_t bytes[4];
39   } ret;
40   ret.bytes[0] = (in >> 24) & 0xff;
41   ret.bytes[1] = (in >> 16) & 0xff;
42   ret.bytes[2] = (in >> 8) & 0xff;
43   ret.bytes[3] = in & 0xff;
44   return ret.word;
45 }
46 
47 /* Converts a 64-bit unsigned integer from host to big-endian byte order. */
48 uint64_t avb_htobe64(uint64_t in) {
49   union {
50     uint64_t word;
51     uint8_t bytes[8];
52   } ret;
53   ret.bytes[0] = (in >> 56) & 0xff;
54   ret.bytes[1] = (in >> 48) & 0xff;
55   ret.bytes[2] = (in >> 40) & 0xff;
56   ret.bytes[3] = (in >> 32) & 0xff;
57   ret.bytes[4] = (in >> 24) & 0xff;
58   ret.bytes[5] = (in >> 16) & 0xff;
59   ret.bytes[6] = (in >> 8) & 0xff;
60   ret.bytes[7] = in & 0xff;
61   return ret.word;
62 }
63 
64 int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
65   const unsigned char* us1 = s1;
66   const unsigned char* us2 = s2;
67   int result = 0;
68 
69   if (0 == n) {
70     return 0;
71   }
72 
73   /*
74    * Code snippet without data-dependent branch due to Nate Lawson
75    * (nate@root.org) of Root Labs.
76    */
77   while (n--) {
78     result |= *us1++ ^ *us2++;
79   }
80 
81   return result != 0;
82 }
83 
84 bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
85   uint64_t original_value;
86 
87   avb_assert(value != NULL);
88 
89   original_value = *value;
90 
91   *value += value_to_add;
92   if (*value < original_value) {
93     avb_error("Overflow when adding values.\n");
94     return false;
95   }
96 
97   return true;
98 }
99 
100 bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
101   uint64_t dummy;
102   if (out_result == NULL) {
103     out_result = &dummy;
104   }
105   *out_result = a;
106   return avb_safe_add_to(out_result, b);
107 }
108 
109 bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
110   size_t n;
111   unsigned int num_cc;
112 
113   for (n = 0, num_cc = 0; n < num_bytes; n++) {
114     uint8_t c = data[n];
115 
116     if (num_cc > 0) {
117       if ((c & (0x80 | 0x40)) == 0x80) {
118         /* 10xx xxxx */
119       } else {
120         goto fail;
121       }
122       num_cc--;
123     } else {
124       if (c < 0x80) {
125         num_cc = 0;
126       } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
127         /* 110x xxxx */
128         num_cc = 1;
129       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
130         /* 1110 xxxx */
131         num_cc = 2;
132       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
133                  (0x80 | 0x40 | 0x20 | 0x10)) {
134         /* 1111 0xxx */
135         num_cc = 3;
136       } else {
137         goto fail;
138       }
139     }
140   }
141 
142   if (num_cc != 0) {
143     goto fail;
144   }
145 
146   return true;
147 
148 fail:
149   return false;
150 }
151 
152 bool avb_str_concat(char* buf,
153                     size_t buf_size,
154                     const char* str1,
155                     size_t str1_len,
156                     const char* str2,
157                     size_t str2_len) {
158   uint64_t combined_len;
159 
160   if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
161     avb_error("Overflow when adding string sizes.\n");
162     return false;
163   }
164 
165   if (combined_len > buf_size - 1) {
166     avb_error("Insufficient buffer space.\n");
167     return false;
168   }
169 
170   avb_memcpy(buf, str1, str1_len);
171   avb_memcpy(buf + str1_len, str2, str2_len);
172   buf[combined_len] = '\0';
173 
174   return true;
175 }
176 
177 void* avb_malloc(size_t size) {
178   void* ret = avb_malloc_(size);
179   if (ret == NULL) {
180     avb_error("Failed to allocate memory.\n");
181     return NULL;
182   }
183   return ret;
184 }
185 
186 void* avb_calloc(size_t size) {
187   void* ret = avb_malloc(size);
188   if (ret == NULL) {
189     return NULL;
190   }
191 
192   avb_memset(ret, '\0', size);
193   return ret;
194 }
195 
196 char* avb_strdup(const char* str) {
197   size_t len = avb_strlen(str);
198   char* ret = avb_malloc(len + 1);
199   if (ret == NULL) {
200     return NULL;
201   }
202 
203   avb_memcpy(ret, str, len);
204   ret[len] = '\0';
205 
206   return ret;
207 }
208 
209 const char* avb_strstr(const char* haystack, const char* needle) {
210   size_t n, m;
211 
212   /* Look through |haystack| and check if the first character of
213    * |needle| matches. If so, check the rest of |needle|.
214    */
215   for (n = 0; haystack[n] != '\0'; n++) {
216     if (haystack[n] != needle[0]) {
217       continue;
218     }
219 
220     for (m = 1;; m++) {
221       if (needle[m] == '\0') {
222         return haystack + n;
223       }
224 
225       if (haystack[n + m] != needle[m]) {
226         break;
227       }
228     }
229   }
230 
231   return NULL;
232 }
233 
234 const char* avb_strv_find_str(const char* const* strings,
235                               const char* str,
236                               size_t str_size) {
237   size_t n;
238   for (n = 0; strings[n] != NULL; n++) {
239     if (avb_strlen(strings[n]) == str_size &&
240         avb_memcmp(strings[n], str, str_size) == 0) {
241       return strings[n];
242     }
243   }
244   return NULL;
245 }
246 
247 char* avb_replace(const char* str, const char* search, const char* replace) {
248   char* ret = NULL;
249   size_t ret_len = 0;
250   size_t search_len, replace_len;
251   const char* str_after_last_replace;
252 
253   search_len = avb_strlen(search);
254   replace_len = avb_strlen(replace);
255 
256   str_after_last_replace = str;
257   while (*str != '\0') {
258     const char* s;
259     size_t num_before;
260     size_t num_new;
261 
262     s = avb_strstr(str, search);
263     if (s == NULL) {
264       break;
265     }
266 
267     num_before = s - str;
268 
269     if (ret == NULL) {
270       num_new = num_before + replace_len + 1;
271       ret = avb_malloc(num_new);
272       if (ret == NULL) {
273         goto out;
274       }
275       avb_memcpy(ret, str, num_before);
276       avb_memcpy(ret + num_before, replace, replace_len);
277       ret[num_new - 1] = '\0';
278       ret_len = num_new - 1;
279     } else {
280       char* new_str;
281       num_new = ret_len + num_before + replace_len + 1;
282       new_str = avb_malloc(num_new);
283       if (new_str == NULL) {
284         goto out;
285       }
286       avb_memcpy(new_str, ret, ret_len);
287       avb_memcpy(new_str + ret_len, str, num_before);
288       avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
289       new_str[num_new - 1] = '\0';
290       avb_free(ret);
291       ret = new_str;
292       ret_len = num_new - 1;
293     }
294 
295     str = s + search_len;
296     str_after_last_replace = str;
297   }
298 
299   if (ret == NULL) {
300     ret = avb_strdup(str_after_last_replace);
301     if (ret == NULL) {
302       goto out;
303     }
304   } else {
305     size_t num_remaining = avb_strlen(str_after_last_replace);
306     size_t num_new = ret_len + num_remaining + 1;
307     char* new_str = avb_malloc(num_new);
308     if (new_str == NULL) {
309       goto out;
310     }
311     avb_memcpy(new_str, ret, ret_len);
312     avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
313     new_str[num_new - 1] = '\0';
314     avb_free(ret);
315     ret = new_str;
316     ret_len = num_new - 1;
317   }
318 
319 out:
320   return ret;
321 }
322 
323 /* We only support a limited amount of strings in avb_strdupv(). */
324 #define AVB_STRDUPV_MAX_NUM_STRINGS 32
325 
326 char* avb_strdupv(const char* str, ...) {
327   va_list ap;
328   const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
329   size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
330   size_t num_strings, n;
331   uint64_t total_length;
332   char *ret = NULL, *dest;
333 
334   num_strings = 0;
335   total_length = 0;
336   va_start(ap, str);
337   do {
338     size_t str_len = avb_strlen(str);
339     strings[num_strings] = str;
340     lengths[num_strings] = str_len;
341     if (!avb_safe_add_to(&total_length, str_len)) {
342       avb_fatal("Overflow while determining total length.\n");
343       break;
344     }
345     num_strings++;
346     if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
347       avb_fatal("Too many strings passed.\n");
348       break;
349     }
350     str = va_arg(ap, const char*);
351   } while (str != NULL);
352   va_end(ap);
353 
354   ret = avb_malloc(total_length + 1);
355   if (ret == NULL) {
356     goto out;
357   }
358 
359   dest = ret;
360   for (n = 0; n < num_strings; n++) {
361     avb_memcpy(dest, strings[n], lengths[n]);
362     dest += lengths[n];
363   }
364   *dest = '\0';
365   avb_assert(dest == ret + total_length);
366 
367 out:
368   return ret;
369 }
370 
371 const char* avb_basename(const char* str) {
372   int64_t n;
373   size_t len;
374 
375   len = avb_strlen(str);
376   if (len >= 2) {
377     for (n = len - 2; n >= 0; n--) {
378       if (str[n] == '/') {
379         return str + n + 1;
380       }
381     }
382   }
383   return str;
384 }
385 
386 void avb_uppercase(char* str) {
387   size_t i;
388   for (i = 0; str[i] != '\0'; ++i) {
389     if (str[i] <= 0x7A && str[i] >= 0x61) {
390       str[i] -= 0x20;
391     }
392   }
393 }
394 
395 char* avb_bin2hex(const uint8_t* data, size_t data_len) {
396   const char hex_digits[17] = "0123456789abcdef";
397   char* hex_data;
398   size_t n;
399 
400   hex_data = avb_malloc(data_len * 2 + 1);
401   if (hex_data == NULL) {
402     return NULL;
403   }
404 
405   for (n = 0; n < data_len; n++) {
406     hex_data[n * 2] = hex_digits[data[n] >> 4];
407     hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
408   }
409   hex_data[n * 2] = '\0';
410   return hex_data;
411 }
412