Add bootutil support for encrypted images

This allows storing encrypted images in slot1, that are automatically
decrypted when copying to slot0 and re-encrypted when copying from slot0
to slot1.

The encryption works by applying AES-CTR-128 on the image blocks
(excluding the header and TLVs) using a random key. This random key
is itself encrypted using either RSA-OAEP-2048 or AES-KW-128 (AES keywrap
as defined by RFC3394), and appended to the image as newly defined TLVs.

AES-CTR-128 was chosen primarily for having stream cipher proporties,
which basically means that any block being encrypted/decrypted does not
depend on any other previous blocks results.

The TLV adds about 256 bytes to the image in RSA-OAEP-2048 mode, and 24
bytes in AES-KW-128 mode. Resulting sizes for a Mynewt generated mcuboot
(frdm-k64f):

- swap mode and no signing: 12KB
- adding encryption with RSA-OAEP-2048: 28KB
- adding encryption with AES-KW-128: 20KB

Some extra comments:

- AES-KW-128 requires a fairly new mbedtls with nist_kw support.
- An alternative methods which could be added later are ECIES.
- Key-wrapping seems easy enough to implement using just standard
  AES-ECB mode that it should be straight-forward to also add support to
  tinycrypt.

Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c
index f9dcde3..e2e989c 100644
--- a/boot/bootutil/src/image_validate.c
+++ b/boot/bootutil/src/image_validate.c
@@ -32,7 +32,10 @@
 
 #include "mcuboot_config/mcuboot_config.h"
 
-#ifdef MCUBOOT_SIGN_RSA
+#ifdef MCUBOOT_ENC_IMAGES
+#include "bootutil/enc_key.h"
+#endif
+#if defined(MCUBOOT_SIGN_RSA)
 #include "mbedtls/rsa.h"
 #endif
 #if defined(MCUBOOT_SIGN_EC) || defined(MCUBOOT_SIGN_EC256)
@@ -55,6 +58,10 @@
     uint32_t size;
     uint32_t off;
     int rc;
+#ifdef MCUBOOT_ENC_IMAGES
+    uint32_t blk_off;
+    uint8_t idx;
+#endif
 
     bootutil_sha256_init(&sha256_ctx);
 
@@ -64,11 +71,21 @@
         bootutil_sha256_update(&sha256_ctx, seed, seed_len);
     }
 
+#ifdef MCUBOOT_ENC_IMAGES
+    /* Encrypted images only exist in slot1 */
+    if (fap->fa_id == FLASH_AREA_IMAGE_1 &&
+            (hdr->ih_flags & IMAGE_F_ENCRYPTED) &&
+            !boot_enc_valid(fap)) {
+        return -1;
+    }
+#endif
+
     /*
      * Hash is computed over image header and image itself. No TLV is
      * included ATM.
      */
     size = hdr->ih_img_size + hdr->ih_hdr_size;
+    assert(tmp_buf_sz > hdr->ih_hdr_size);
     for (off = 0; off < size; off += blk_sz) {
         blk_sz = size - off;
         if (blk_sz > tmp_buf_sz) {
@@ -78,6 +95,20 @@
         if (rc) {
             return rc;
         }
+#ifdef MCUBOOT_ENC_IMAGES
+        if (fap->fa_id == FLASH_AREA_IMAGE_1 && hdr->ih_flags & IMAGE_F_ENCRYPTED) {
+            /* FIXME: fails if header size is larger than blk_sz */
+            if (off < hdr->ih_hdr_size) {
+                idx = hdr->ih_hdr_size;
+                blk_off = 0;
+            } else {
+                idx = 0;
+                blk_off = (off - hdr->ih_hdr_size) & 0xf;
+            }
+            boot_encrypt(fap, (off + idx) - hdr->ih_hdr_size, blk_sz - idx,
+                    blk_off, &tmp_buf[idx]);
+        }
+#endif
         bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
     }
     bootutil_sha256_finish(&sha256_ctx, hash_result);
@@ -154,8 +185,7 @@
     uint8_t hash[32];
     int rc;
 
-    rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
-                           seed, seed_len);
+    rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len);
     if (rc) {
         return rc;
     }