add option for rollback protection

Depends on 'MCUBOOT_OVERWRITE_ONLY' option since swap info is not protected
by signature

Signed-off-by: Håkon Øye Amundsen <haakon.amundsen@nordicsemi.no>
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 06463a8..4b8a3a2 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -510,6 +510,42 @@
     return 0;
 }
 
+#if (BOOT_IMAGE_NUMBER > 1) || \
+    (defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
+/**
+ * Check if the version of the image is not older than required.
+ *
+ * @param req         Required minimal image version.
+ * @param ver         Version of the image to be checked.
+ *
+ * @return            0 if the version is sufficient, nonzero otherwise.
+ */
+static int
+boot_is_version_sufficient(struct image_version *req,
+                           struct image_version *ver)
+{
+    if (ver->iv_major > req->iv_major) {
+        return 0;
+    }
+    if (ver->iv_major < req->iv_major) {
+        return BOOT_EBADVERSION;
+    }
+    /* The major version numbers are equal. */
+    if (ver->iv_minor > req->iv_minor) {
+        return 0;
+    }
+    if (ver->iv_minor < req->iv_minor) {
+        return BOOT_EBADVERSION;
+    }
+    /* The minor version numbers are equal. */
+    if (ver->iv_revision < req->iv_revision) {
+        return BOOT_EBADVERSION;
+    }
+
+    return 0;
+}
+#endif
+
 /*
  * Check that there is a valid image in a slot
  *
@@ -541,6 +577,24 @@
         goto out;
     }
 
+#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
+    if (slot != BOOT_PRIMARY_SLOT) {
+        /* Check if version of secondary slot is sufficient */
+        rc = boot_is_version_sufficient(
+                &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver,
+                &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver);
+        if (rc != 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
+            BOOT_LOG_ERR("insufficient version in secondary slot");
+            flash_area_erase(fap, 0, fap->fa_size);
+            /* Image in the secondary slot does not satisfy version requirement.
+             * Erase the image and continue booting from the primary slot.
+             */
+            rc = 1;
+            goto out;
+        }
+    }
+#endif
+
     if (!boot_is_header_valid(hdr, fap) || boot_image_check(state, hdr, fap, bs)) {
         if (slot != BOOT_PRIMARY_SLOT) {
             flash_area_erase(fap, 0, fap->fa_size);
@@ -552,7 +606,7 @@
         BOOT_LOG_ERR("Image in the %s slot is not valid!",
                      (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
 #endif
-        rc = -1;
+        rc = 1;
         goto out;
     }
 
@@ -967,39 +1021,6 @@
 
 #if (BOOT_IMAGE_NUMBER > 1)
 /**
- * Check if the version of the image is not older than required.
- *
- * @param req         Required minimal image version.
- * @param ver         Version of the image to be checked.
- *
- * @return            0 if the version is sufficient, nonzero otherwise.
- */
-static int
-boot_is_version_sufficient(struct image_version *req,
-                           struct image_version *ver)
-{
-    if (ver->iv_major > req->iv_major) {
-        return 0;
-    }
-    if (ver->iv_major < req->iv_major) {
-        return BOOT_EBADVERSION;
-    }
-    /* The major version numbers are equal. */
-    if (ver->iv_minor > req->iv_minor) {
-        return 0;
-    }
-    if (ver->iv_minor < req->iv_minor) {
-        return BOOT_EBADVERSION;
-    }
-    /* The minor version numbers are equal. */
-    if (ver->iv_revision < req->iv_revision) {
-        return BOOT_EBADVERSION;
-    }
-
-    return 0;
-}
-
-/**
  * Check the image dependency whether it is satisfied and modify
  * the swap type if necessary.
  *