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;
}