uboot/lib/libavb/avb_property_descriptor.c
<<
>>
Prefs
   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
   9bool 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
  42typedef struct {
  43  const char* key;
  44  size_t key_size;
  45  const char* ret_value;
  46  size_t ret_value_size;
  47} PropertyIteratorData;
  48
  49static 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
  84out:
  85  return ret;
  86}
  87
  88const 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
 116bool 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
 164out:
 165  return ret;
 166}
 167