Boot: Add TLV iterator API

Add TLV iterator API to MCUBoot as part of a partial synchronization
with the mainstream MCUBoot repository. The hash of the source commit:
61fd888a7f4d741714553f36839dd49fb0065731.

Change-Id: I817b199f4923433010253c4a201ada250f743aa8
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/bl2/ext/mcuboot/bootutil/src/image_validate.c b/bl2/ext/mcuboot/bootutil/src/image_validate.c
index 841f183..8c554ee 100644
--- a/bl2/ext/mcuboot/bootutil/src/image_validate.c
+++ b/bl2/ext/mcuboot/bootutil/src/image_validate.c
@@ -20,7 +20,7 @@
 /*
  * Original code taken from mcuboot project at:
  * https://github.com/JuulLabs-OSS/mcuboot
- * Git SHA of the original version: 4f0ea747c314547daa6b6299ccbd77ae4dee6758
+ * Git SHA of the original version: 61fd888a7f4d741714553f36839dd49fb0065731
  * Modifications are Copyright (c) 2018-2019 Arm Limited.
  */
 
@@ -276,7 +276,8 @@
                       int seed_len, uint8_t *out_hash)
 {
     uint32_t off;
-    uint32_t end;
+    uint16_t len;
+    uint8_t type;
     int sha256_valid = 0;
 #ifdef EXPECTED_SIG_TLV
     int valid_signature = 0;
@@ -286,7 +287,7 @@
     uint8_t key_buf[SIG_BUF_SIZE + 24];
 #endif
 #endif
-    struct image_tlv tlv;
+    struct image_tlv_iter it;
     uint8_t buf[SIG_BUF_SIZE];
     uint8_t hash[32] = {0};
     uint32_t security_cnt;
@@ -304,7 +305,7 @@
         memcpy(out_hash, hash, 32);
     }
 
-    rc = boot_find_tlv_offs(hdr, fap, &off, &end);
+    rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
     if (rc) {
         return rc;
     }
@@ -313,22 +314,23 @@
      * Traverse through all of the TLVs, performing any checks we know
      * and are able to do.
      */
-    while (off < end) {
-        rc = LOAD_IMAGE_DATA(hdr, fap, off, &tlv, sizeof(tlv));
-        if (rc) {
-            return rc;
+    while (true) {
+        rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
+        if (rc < 0) {
+            return -1;
+        } else if (rc > 0) {
+            break;
         }
 
-        if (tlv.it_type == IMAGE_TLV_SHA256) {
+        if (type == IMAGE_TLV_SHA256) {
             /*
              * Verify the SHA256 image hash.  This must always be
              * present.
              */
-            if (tlv.it_len != sizeof(hash)) {
+            if (len != sizeof(hash)) {
                 return -1;
             }
-            rc = LOAD_IMAGE_DATA(hdr, fap, off + sizeof(tlv),
-                                 buf, sizeof(hash));
+            rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash));
             if (rc) {
                 return rc;
             }
@@ -339,72 +341,70 @@
             sha256_valid = 1;
 #ifdef EXPECTED_SIG_TLV
 #ifndef MCUBOOT_HW_KEY
-        } else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
+        } else if (type == IMAGE_TLV_KEYHASH) {
             /*
              * Determine which key we should be checking.
              */
-            if (tlv.it_len > 32) {
+            if (len > 32) {
                 return -1;
             }
-            rc = LOAD_IMAGE_DATA(hdr, fap, off + sizeof(tlv), buf, tlv.it_len);
+            rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
             if (rc) {
                 return rc;
             }
-            key_id = bootutil_find_key(buf, tlv.it_len);
+            key_id = bootutil_find_key(buf, len);
             /*
              * The key may not be found, which is acceptable.  There
              * can be multiple signatures, each preceded by a key.
              */
 #else /* MCUBOOT_HW_KEY */
-        } else if (tlv.it_type == IMAGE_TLV_KEY) {
+        } else if (type == IMAGE_TLV_KEY) {
             /*
              * Determine which key we should be checking.
              */
-            if (tlv.it_len > sizeof(key_buf)) {
+            if (len > sizeof(key_buf)) {
                 return -1;
             }
-            rc = LOAD_IMAGE_DATA(hdr, fap, off + sizeof(tlv),
-                                 key_buf, tlv.it_len);
+            rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
             if (rc) {
                 return rc;
             }
-            key_id = bootutil_find_key(image_index, key_buf, tlv.it_len);
+            key_id = bootutil_find_key(image_index, key_buf, len);
             /*
              * The key may not be found, which is acceptable.  There
              * can be multiple signatures, each preceded by a key.
              */
 #endif /* MCUBOOT_HW_KEY */
-        } else if (tlv.it_type == EXPECTED_SIG_TLV) {
+        } else if (type == EXPECTED_SIG_TLV) {
             /* Ignore this signature if it is out of bounds. */
-            if (key_id >= 0 && key_id < bootutil_key_cnt) {
-                if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
-                    return -1;
-                }
-                rc = LOAD_IMAGE_DATA(hdr, fap, off + sizeof(tlv),
-                                     buf, tlv.it_len);
-                if (rc) {
-                    return -1;
-                }
-                rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len,
-                                         key_id);
-                if (rc == 0) {
-                    valid_signature = 1;
-                }
+            if (key_id < 0 || key_id >= bootutil_key_cnt) {
+                key_id = -1;
+                continue;
+            }
+            if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) {
+                return -1;
+            }
+            rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
+            if (rc) {
+                return -1;
+            }
+            rc = bootutil_verify_sig(hash, sizeof(hash), buf, len, key_id);
+            if (rc == 0) {
+                valid_signature = 1;
             }
             key_id = -1;
 #endif
-        } else if (tlv.it_type == IMAGE_TLV_SEC_CNT) {
+        } else if (type == IMAGE_TLV_SEC_CNT) {
             /*
              * Verify the image's security counter.
              * This must always be present.
              */
-            if (tlv.it_len != sizeof(img_security_cnt)) {
+            if (len != sizeof(img_security_cnt)) {
                 /* Security counter is not valid. */
                 return -1;
             }
 
-            rc = LOAD_IMAGE_DATA(hdr, fap, off + sizeof(tlv),
-                                 &img_security_cnt, tlv.it_len);
+            rc = LOAD_IMAGE_DATA(hdr, fap, off, &img_security_cnt, len);
             if (rc) {
                 return rc;
             }
@@ -425,14 +425,6 @@
             /* The image's security counter has been successfully verified. */
             security_counter_valid = 1;
         }
-
-        /* Avoid integer overflow. */
-        if (boot_add_uint32_overflow_check(off, (sizeof(tlv) + tlv.it_len))) {
-            /* Potential overflow. */
-            break;
-        } else {
-            off += sizeof(tlv) + tlv.it_len;
-        }
     }
 
     if (!sha256_valid || !security_counter_valid) {