Implement new swap scheme for devices with large erase size using scratch with status area
diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py
index 257c892..ec18fa5 100644
--- a/scripts/imgtool/image.py
+++ b/scripts/imgtool/image.py
@@ -157,6 +157,9 @@
         self.enckey = None
         self.save_enctlv = save_enctlv
         self.enctlv_len = 0
+        self.hkdf_salt = None
+        self.hkdf_len = 48
+        self.enc_nonce = bytes([0] * 16)
 
         if security_counter == 'auto':
             # Security counter has not been explicitly provided,
@@ -228,7 +231,7 @@
                                                   self.save_enctlv,
                                                   self.enctlv_len)
                 trailer_addr = (self.base_addr + self.slot_size) - trailer_size
-                padding = bytearray([self.erased_val] * 
+                padding = bytearray([self.erased_val] *
                                     (trailer_size - len(boot_magic)))
                 if self.confirm and not self.overwrite_only:
                     padding[-MAX_ALIGN] = 0x01  # image_ok = 0x01
@@ -267,13 +270,18 @@
             newpk = X25519PrivateKey.generate()
             shared = newpk.exchange(enckey._get_public())
         derived_key = HKDF(
-            algorithm=hashes.SHA256(), length=48, salt=None,
+            algorithm=hashes.SHA256(), length=self.hkdf_len, salt=self.hkdf_salt,
             info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared)
+        if self.hkdf_salt is not None:
+            key_nonce = derived_key[48:64]
+            self.enc_nonce = derived_key[64:76] + bytes([0] * 4)
+        else:
+            key_nonce = bytes([0] * 16)
         encryptor = Cipher(algorithms.AES(derived_key[:16]),
-                           modes.CTR(bytes([0] * 16)),
+                           modes.CTR(key_nonce),
                            backend=default_backend()).encryptor()
         cipherkey = encryptor.update(plainkey) + encryptor.finalize()
-        mac = hmac.HMAC(derived_key[16:], hashes.SHA256(),
+        mac = hmac.HMAC(derived_key[16:48], hashes.SHA256(),
                         backend=default_backend())
         mac.update(cipherkey)
         ciphermac = mac.finalize()
@@ -288,9 +296,13 @@
         return cipherkey, ciphermac, pubk
 
     def create(self, key, public_key_format, enckey, dependencies=None,
-               sw_type=None, custom_tlvs=None):
+               sw_type=None, custom_tlvs=None, use_random_iv=False):
         self.enckey = enckey
 
+        if use_random_iv:
+            self.hkdf_salt = os.urandom(32)
+            self.hkdf_len  += 16 * 2   # 48 for basic scheme + 16 * 2 for random IVs
+
         # Calculate the hash of the public key
         if key is not None:
             pub = key.get_public_bytes()
@@ -443,13 +455,15 @@
                                      x25519.X25519Public)):
                 cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey)
                 enctlv = pubk + mac + cipherkey
+                if self.hkdf_salt is not None:
+                    enctlv += self.hkdf_salt
                 self.enctlv_len = len(enctlv)
                 if isinstance(enckey, ecdsa.ECDSA256P1Public):
                     tlv.add('ENCEC256', enctlv)
                 else:
                     tlv.add('ENCX25519', enctlv)
 
-            nonce = bytes([0] * 16)
+            nonce = self.enc_nonce
             cipher = Cipher(algorithms.AES(plainkey), modes.CTR(nonce),
                             backend=default_backend())
             encryptor = cipher.encryptor()
diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py
index 6188e78..53f4d98 100755
--- a/scripts/imgtool/main.py
+++ b/scripts/imgtool/main.py
@@ -290,6 +290,9 @@
               default='hash', help='In what format to add the public key to '
               'the image manifest: full key or hash of the key.')
 @click.option('-k', '--key', metavar='filename')
+@click.option('--use-random-iv', default=False, is_flag=True,
+              help='Use random Salt and IV (initial vectors) for the image '
+              'encrypting scheme')
 @click.command(help='''Create a signed or unsigned image\n
                INFILE and OUTFILE are parsed as Intel HEX if the params have
                .hex extension, otherwise binary format is used''')
@@ -297,7 +300,7 @@
          pad_header, slot_size, pad, confirm, max_sectors, overwrite_only,
          endian, encrypt, infile, outfile, dependencies, load_addr, hex_addr,
          erased_val, save_enctlv, security_counter, boot_record, custom_tlv,
-         rom_fixed):
+         rom_fixed, use_random_iv):
 
     if confirm:
         # Confirmed but non-padded images don't make much sense, because
@@ -344,7 +347,7 @@
             custom_tlvs[tag] = value.encode('utf-8')
 
     img.create(key, public_key_format, enckey, dependencies, boot_record,
-               custom_tlvs)
+               custom_tlvs, use_random_iv=use_random_iv)
     img.save(outfile, hex_addr)