Boot: Add constant time memory equality function

Add boot_secure_memequal function which runs in constant time,
mitigating the risk of timing side channel attacks. Replace calls to
memcmp where applicable (where they test only equality).

Change-Id: I062a433a67a1a865d6e890ba06a75bfb6b13deb3
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
index ecd2874..9ce0ff1 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
@@ -101,10 +101,36 @@
 #define BOOT_SWAP_TABLES_COUNT \
     (sizeof(boot_swap_tables) / sizeof(boot_swap_tables[0]))
 
+/**
+ * @brief Determine if the data at two memory addresses is equal
+ *
+ * @param s1    The first memory region to compare.
+ * @param s2    The second memory region to compare.
+ * @param n     The amount of bytes to compare.
+ *
+ * @note        This function does not comply with the specification of memcmp,
+ *              so should not be considered a drop-in replacement.
+ *
+ * @return      0 if memory regions are equal.
+ */
+uint32_t boot_secure_memequal(const void *s1, const void *s2, size_t n)
+{
+    size_t i;
+    uint8_t *s1_p = (uint8_t*) s1;
+    uint8_t *s2_p = (uint8_t*) s2;
+    uint32_t ret = 0;
+
+    for (i = 0; i < n; i++) {
+        ret |= (s1_p[i] ^ s2_p[i]);
+    }
+
+    return ret;
+}
+
 static int
 boot_magic_decode(const uint32_t *magic)
 {
-    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+    if (boot_secure_memequal(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
         return BOOT_MAGIC_GOOD;
     }
     return BOOT_MAGIC_BAD;
@@ -327,7 +353,7 @@
         goto out;
     }
 
-    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
+    if (boot_secure_memequal(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
         /*
          * If the primary slot's magic is not valid, try scratch...
          */
@@ -346,7 +372,7 @@
             goto out;
         }
 
-        assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
+        assert(boot_secure_memequal(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
     }
 
     off = boot_swap_size_off(fap);
diff --git a/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h b/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
index 6a6fad6..f8e1012 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
@@ -204,6 +204,7 @@
     uint8_t write_sz;
 };
 
+uint32_t boot_secure_memequal(const void *s1, const void *s2, size_t n);
 int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
                         size_t slen, uint8_t key_id);
 
diff --git a/bl2/ext/mcuboot/bootutil/src/image_rsa.c b/bl2/ext/mcuboot/bootutil/src/image_rsa.c
index 22dc6e3..ae71d9b 100644
--- a/bl2/ext/mcuboot/bootutil/src/image_rsa.c
+++ b/bl2/ext/mcuboot/bootutil/src/image_rsa.c
@@ -263,7 +263,7 @@
 
     /* Step 14.  If H = H', output "consistent".  Otherwise, output
      * "inconsistent". */
-    if (memcmp(h2, &em[PSS_HASH_OFFSET], PSS_HLEN) != 0) {
+    if (boot_secure_memequal(h2, &em[PSS_HASH_OFFSET], PSS_HLEN) != 0) {
         return -1;
     }
 
diff --git a/bl2/ext/mcuboot/bootutil/src/image_validate.c b/bl2/ext/mcuboot/bootutil/src/image_validate.c
index 931f459..d471155 100644
--- a/bl2/ext/mcuboot/bootutil/src/image_validate.c
+++ b/bl2/ext/mcuboot/bootutil/src/image_validate.c
@@ -146,7 +146,7 @@
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
         return -1;
     }
-    if (!memcmp(hash, key_hash, key_hash_size)) {
+    if (!boot_secure_memequal(hash, key_hash, key_hash_size)) {
         bootutil_keys[0].key = key;
         pub_key_len = key_len;
         return 0;
@@ -169,7 +169,7 @@
         bootutil_sha256_init(&sha256_ctx);
         bootutil_sha256_update(&sha256_ctx, key->key, *key->len);
         bootutil_sha256_finish(&sha256_ctx, hash);
-        if (!memcmp(hash, keyhash, keyhash_len)) {
+        if (!boot_secure_memequal(hash, keyhash, keyhash_len)) {
             return i;
         }
     }
@@ -229,7 +229,7 @@
                 return -1;
             }
 
-            if (memcmp(hash, (uint32_t *)(load_address + off + tlv_sz),
+            if (boot_secure_memequal(hash, (uint32_t *)(load_address + off + tlv_sz),
                        sizeof(hash))) {
                 return -1;
             }
@@ -419,7 +419,7 @@
             if (rc) {
                 return rc;
             }
-            if (memcmp(hash, buf, sizeof(hash))) {
+            if (boot_secure_memequal(hash, buf, sizeof(hash))) {
                 return -1;
             }