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/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index 8dcca2a..6f85ff1 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -33,6 +33,9 @@
 #include "bootutil/bootutil.h"
 #include "bootutil_priv.h"
 #include "bootutil/bootutil_log.h"
+#ifdef MCUBOOT_ENC_IMAGES
+#include "bootutil/enc_key.h"
+#endif
 
 int boot_current_slot;
 
@@ -122,15 +125,26 @@
 {
     return /* state for all sectors */
            BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
-           BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */        +
+#ifdef MCUBOOT_ENC_IMAGES
+           /* encryption keys */
+           BOOT_ENC_KEY_SIZE * 2                  +
+#endif
+           /* copy_done + image_ok + swap_size */
+           BOOT_MAX_ALIGN * 3                     +
            BOOT_MAGIC_SZ;
 }
 
 static uint32_t
 boot_scratch_trailer_sz(uint8_t min_write_sz)
 {
-    return BOOT_STATUS_STATE_COUNT * min_write_sz +  /* state for one sector */
-           BOOT_MAX_ALIGN * 2                     +  /* image_ok + swap_size */
+           /* state for one sector */
+    return BOOT_STATUS_STATE_COUNT * min_write_sz +
+#ifdef MCUBOOT_ENC_IMAGES
+           /* encryption keys */
+           BOOT_ENC_KEY_SIZE * 2                  +
+#endif
+           /* image_ok + swap_size */
+           BOOT_MAX_ALIGN * 2                     +
            BOOT_MAGIC_SZ;
 }
 
@@ -202,6 +216,20 @@
     return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
 }
 
+#ifdef MCUBOOT_ENC_IMAGES
+static uint32_t
+boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
+{
+    if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
+        return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2 -
+                              ((slot + 1) * BOOT_ENC_KEY_SIZE);
+    }
+
+    return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3 -
+                          ((slot + 1) * BOOT_ENC_KEY_SIZE);
+}
+#endif
+
 int
 boot_read_swap_state(const struct flash_area *fap,
                      struct boot_swap_state *state)
@@ -337,6 +365,60 @@
     return rc;
 }
 
+#ifdef MCUBOOT_ENC_IMAGES
+int
+boot_read_enc_key(uint8_t slot, uint8_t *enckey)
+{
+    uint32_t magic[BOOT_MAGIC_SZ];
+    uint32_t off;
+    const struct flash_area *fap;
+    int rc;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    off = boot_magic_off(fap);
+    rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto out;
+    }
+
+    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
+        /*
+         * If Slot 0 's magic is not valid, try scratch...
+         */
+
+        flash_area_close(fap);
+
+        rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
+        if (rc != 0) {
+            return BOOT_EFLASH;
+        }
+
+        off = boot_magic_off(fap);
+        rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+        if (rc != 0) {
+            rc = BOOT_EFLASH;
+            goto out;
+        }
+
+        assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
+    }
+
+    off = boot_enc_key_off(fap, slot);
+    rc = flash_area_read(fap, off, enckey, BOOT_ENC_KEY_SIZE);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+    }
+
+out:
+    flash_area_close(fap);
+    return rc;
+}
+#endif
 
 int
 boot_write_magic(const struct flash_area *fap)
@@ -427,6 +509,23 @@
     return 0;
 }
 
+#ifdef MCUBOOT_ENC_IMAGES
+int
+boot_write_enc_key(const struct flash_area *fap, uint8_t slot, const uint8_t *enckey)
+{
+    uint32_t off;
+    int rc;
+
+    off = boot_enc_key_off(fap, slot);
+    rc = flash_area_write(fap, off, enckey, BOOT_ENC_KEY_SIZE);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+#endif
+
 int
 boot_swap_type(void)
 {