avb_property_descriptor.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. #include "avb_property_descriptor.h"
  25. #include "avb_util.h"
  26. bool avb_property_descriptor_validate_and_byteswap(
  27. const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
  28. uint64_t expected_size;
  29. avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
  30. if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
  31. (AvbDescriptor*)dest))
  32. return false;
  33. if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
  34. avb_error("Invalid tag for property descriptor.\n");
  35. return false;
  36. }
  37. dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
  38. dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
  39. /* Check that key and value are fully contained. */
  40. expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
  41. if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
  42. !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
  43. avb_error("Overflow while adding up sizes.\n");
  44. return false;
  45. }
  46. if (expected_size > dest->parent_descriptor.num_bytes_following) {
  47. avb_error("Descriptor payload size overflow.\n");
  48. return false;
  49. }
  50. return true;
  51. }
  52. typedef struct {
  53. const char* key;
  54. size_t key_size;
  55. const char* ret_value;
  56. size_t ret_value_size;
  57. } PropertyIteratorData;
  58. static bool property_lookup_desc_foreach(const AvbDescriptor* header,
  59. void* user_data) {
  60. PropertyIteratorData* data = (PropertyIteratorData*)user_data;
  61. AvbPropertyDescriptor prop_desc;
  62. const uint8_t* p;
  63. bool ret = true;
  64. if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
  65. goto out;
  66. }
  67. if (!avb_property_descriptor_validate_and_byteswap(
  68. (const AvbPropertyDescriptor*)header, &prop_desc)) {
  69. goto out;
  70. }
  71. p = (const uint8_t*)header;
  72. if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
  73. avb_error("No terminating NUL byte in key.\n");
  74. goto out;
  75. }
  76. if (data->key_size == prop_desc.key_num_bytes) {
  77. if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
  78. data->key,
  79. data->key_size) == 0) {
  80. data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
  81. prop_desc.key_num_bytes + 1);
  82. data->ret_value_size = prop_desc.value_num_bytes;
  83. /* Stop iterating. */
  84. ret = false;
  85. goto out;
  86. }
  87. }
  88. out:
  89. return ret;
  90. }
  91. const char* avb_property_lookup(const uint8_t* image_data,
  92. size_t image_size,
  93. const char* key,
  94. size_t key_size,
  95. size_t* out_value_size) {
  96. PropertyIteratorData data;
  97. if (key_size == 0) {
  98. key_size = avb_strlen(key);
  99. }
  100. data.key = key;
  101. data.key_size = key_size;
  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. if (out_value_size != NULL) {
  110. *out_value_size = 0;
  111. }
  112. return NULL;
  113. }
  114. bool avb_property_lookup_uint64(const uint8_t* image_data,
  115. size_t image_size,
  116. const char* key,
  117. size_t key_size,
  118. uint64_t* out_value) {
  119. const char* value;
  120. bool ret = false;
  121. uint64_t parsed_val;
  122. int base;
  123. int n;
  124. value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
  125. if (value == NULL) {
  126. goto out;
  127. }
  128. base = 10;
  129. if (avb_memcmp(value, "0x", 2) == 0) {
  130. base = 16;
  131. value += 2;
  132. }
  133. parsed_val = 0;
  134. for (n = 0; value[n] != '\0'; n++) {
  135. int c = value[n];
  136. int digit;
  137. parsed_val *= base;
  138. if (c >= '0' && c <= '9') {
  139. digit = c - '0';
  140. } else if (base == 16 && c >= 'a' && c <= 'f') {
  141. digit = c - 'a' + 10;
  142. } else if (base == 16 && c >= 'A' && c <= 'F') {
  143. digit = c - 'A' + 10;
  144. } else {
  145. avb_error("Invalid digit.\n");
  146. goto out;
  147. }
  148. parsed_val += digit;
  149. }
  150. ret = true;
  151. if (out_value != NULL) {
  152. *out_value = parsed_val;
  153. }
  154. out:
  155. return ret;
  156. }