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