Define and use read_u{8,16,64}

A large portion of the utility functions is parsing the data structures
on disk. The pattern always involve: reading a certain size of data,
ensuring that there is enough space available; converting the value from
big-endian to host byte order and advancing the pointer pass that value.
Define new functions to capture this task. Use these functions for
parsing the TrillanLogRoot descriptor.

Test: m libavb_host_unittest && ./out/host/linux-x86/nativetest64/libavb_host_unittest/libavb_host_unittest
Test: m libavb_host_unittest && ./out/host/linux-x86/nativetest/libavb_host_unittest/libavb_host_unittest
Bug: 154303414
Change-Id: Ie23639f69804dc6a23c66a5e96c45d8c0ca7586c
diff --git a/libavb_aftl/avb_aftl_util.c b/libavb_aftl/avb_aftl_util.c
index 98387d1..29c2ef5 100644
--- a/libavb_aftl/avb_aftl_util.c
+++ b/libavb_aftl/avb_aftl_util.c
@@ -393,6 +393,35 @@
   return retval;
 }
 
+/* Defines helper functions read_u8, read_u16 and read_u64. These functions can
+ * be used to read from a |data| stream a |value| of a specific size. The value
+ * endianness is converted from big-endian to host.  We ensure that the read do
+ * not overflow beyond |data_end|. If successful, |data| is brought forward by
+ * the size of the value read.
+ */
+#define _read_u(fct)                                   \
+  {                                                    \
+    size_t value_size = sizeof(*value);                \
+    if ((*data + value_size) < *data) return false;    \
+    if ((*data + value_size) > data_end) return false; \
+    avb_memcpy(value, *data, value_size);              \
+    *value = fct(*value);                              \
+    *data += value_size;                               \
+    return true;                                       \
+  }
+static bool read_u8(uint8_t* value, uint8_t** data, uint8_t* data_end) {
+  _read_u();
+}
+AVB_ATTR_WARN_UNUSED_RESULT
+static bool read_u16(uint16_t* value, uint8_t** data, uint8_t* data_end) {
+  _read_u(avb_be16toh);
+}
+AVB_ATTR_WARN_UNUSED_RESULT
+static bool read_u64(uint64_t* value, uint8_t** data, uint8_t* data_end) {
+  _read_u(avb_be64toh);
+}
+AVB_ATTR_WARN_UNUSED_RESULT
+
 /* Allocates and populates a TrillianLogRootDescriptor element in an
    AftlIcpEntry from a binary blob.
    The blob is expected to be pointing to the beginning of a
@@ -403,96 +432,83 @@
 static bool parse_trillian_log_root_descriptor(AftlIcpEntry* icp_entry,
                                                uint8_t** aftl_blob,
                                                size_t aftl_blob_remaining) {
-  size_t parsed_size;
-
   avb_assert(icp_entry);
   avb_assert(aftl_blob);
   avb_assert(aftl_blob_remaining >= AVB_AFTL_MIN_TLRD_SIZE);
+  uint8_t* blob_end = *aftl_blob + aftl_blob_remaining;
+
   /* Copy in the version field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.version),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, version));
-  icp_entry->log_root_descriptor.version =
-      avb_be16toh(icp_entry->log_root_descriptor.version);
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, version);
-  parsed_size = avb_aftl_member_size(TrillianLogRootDescriptor, version);
-  /* Copy in the tree size field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.tree_size),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, tree_size));
-  icp_entry->log_root_descriptor.tree_size =
-      avb_be64toh(icp_entry->log_root_descriptor.tree_size);
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, tree_size);
-  parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, tree_size);
-  /* Copy in the root hash size field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.root_hash_size),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, root_hash_size));
-  if (icp_entry->log_root_descriptor.root_hash_size != AVB_AFTL_HASH_SIZE) {
-    avb_error("Invalid root hash size.\n");
-    free_aftl_icp_entry(icp_entry);
+  if (!read_u16(
+          &(icp_entry->log_root_descriptor.version), aftl_blob, blob_end)) {
+    avb_error("Unable to parse version.\n");
     return false;
   }
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, root_hash_size);
-  parsed_size +=
-      avb_aftl_member_size(TrillianLogRootDescriptor, root_hash_size);
+
+  /* Copy in the tree size field from the blob. */
+  if (!read_u64(
+          &(icp_entry->log_root_descriptor.tree_size), aftl_blob, blob_end)) {
+    avb_error("Unable to parse tree size.\n");
+    return false;
+  }
+
+  /* Copy in the root hash size field from the blob. */
+  if (!read_u8(&(icp_entry->log_root_descriptor.root_hash_size),
+               aftl_blob,
+               blob_end)) {
+    avb_error("Unable to parse root hash size.\n");
+    return false;
+  }
+  if (icp_entry->log_root_descriptor.root_hash_size != AVB_AFTL_HASH_SIZE) {
+    avb_error("Invalid root hash size.\n");
+    return false;
+  }
+
   /* Copy in the root hash from the blob. */
   icp_entry->log_root_descriptor.root_hash =
       (uint8_t*)avb_calloc(icp_entry->log_root_descriptor.root_hash_size);
   if (!icp_entry->log_root_descriptor.root_hash) {
     avb_error("Failure to allocate root hash.\n");
-    free_aftl_icp_entry(icp_entry);
     return false;
   }
-
   avb_memcpy(icp_entry->log_root_descriptor.root_hash,
              *aftl_blob,
              icp_entry->log_root_descriptor.root_hash_size);
   *aftl_blob += icp_entry->log_root_descriptor.root_hash_size;
-  parsed_size += icp_entry->log_root_descriptor.root_hash_size;
+
   /* Copy in the timestamp field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.timestamp),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, timestamp));
-  icp_entry->log_root_descriptor.timestamp =
-      avb_be64toh(icp_entry->log_root_descriptor.timestamp);
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, timestamp);
-  parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, timestamp);
+  if (!read_u64(
+          &(icp_entry->log_root_descriptor.timestamp), aftl_blob, blob_end)) {
+    avb_error("Unable to parse timestamp.\n");
+    return false;
+  }
+
   /* Copy in the revision field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.revision),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, revision));
-  icp_entry->log_root_descriptor.revision =
-      avb_be64toh(icp_entry->log_root_descriptor.revision);
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, revision);
-  parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, revision);
+  if (!read_u64(
+          &(icp_entry->log_root_descriptor.revision), aftl_blob, blob_end)) {
+    avb_error("Unable to parse revision.\n");
+    return false;
+  }
+
   /* Copy in the metadata size field from the blob. */
-  avb_memcpy(&(icp_entry->log_root_descriptor.metadata_size),
-             *aftl_blob,
-             avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size));
-  icp_entry->log_root_descriptor.metadata_size =
-      avb_be16toh(icp_entry->log_root_descriptor.metadata_size);
-  *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size);
-  parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size);
+  if (!read_u16(&(icp_entry->log_root_descriptor.metadata_size),
+                aftl_blob,
+                blob_end)) {
+    avb_error("Unable to parse metadata size.\n");
+    return false;
+  }
+
   if (icp_entry->log_root_descriptor.metadata_size >
       AVB_AFTL_MAX_METADATA_SIZE) {
     avb_error("Invalid metadata size.\n");
-    free_aftl_icp_entry(icp_entry);
     return false;
   }
-  if (icp_entry->log_root_descriptor.metadata_size + parsed_size >
-      aftl_blob_remaining) {
-    avb_error("Invalid AftlImage.\n");
-    free_aftl_icp_entry(icp_entry);
-    return false;
-  }
+
   /* If it exists, copy in the metadata field from the blob. */
   if (icp_entry->log_root_descriptor.metadata_size > 0) {
     icp_entry->log_root_descriptor.metadata =
         (uint8_t*)avb_calloc(icp_entry->log_root_descriptor.metadata_size);
     if (!icp_entry->log_root_descriptor.metadata) {
       avb_error("Failure to allocate metadata.\n");
-      free_aftl_icp_entry(icp_entry);
       return false;
     }
     avb_memcpy(icp_entry->log_root_descriptor.metadata,
@@ -748,6 +764,7 @@
   }
   if (!parse_trillian_log_root_descriptor(
           icp_entry, aftl_blob, icp_entry->log_root_descriptor_size)) {
+    free_aftl_icp_entry(icp_entry);
     return NULL;
   }