diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 28e827fea..aeedff40e 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -35,13 +35,16 @@ #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif -#if defined(MCUBOOT_SIGN_EC384) +#if defined(MCUBOOT_SHA512) + #define IMAGE_HASH_SIZE (64) + #define EXPECTED_HASH_TLV IMAGE_TLV_SHA512 +#elif defined(MCUBOOT_SIGN_EC384) #define IMAGE_HASH_SIZE (48) #define EXPECTED_HASH_TLV IMAGE_TLV_SHA384 #else #define IMAGE_HASH_SIZE (32) #define EXPECTED_HASH_TLV IMAGE_TLV_SHA256 -#endif /* MCUBOOT_SIGN_EC384 */ +#endif /* MCUBOOT_SIGN */ /* Universal defines for SHA-256 */ #define BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE (64) @@ -83,7 +86,9 @@ typedef psa_hash_operation_t bootutil_sha_context; static inline int bootutil_sha_init(bootutil_sha_context *ctx) { *ctx = psa_hash_operation_init(); -#if defined(MCUBOOT_SIGN_EC384) +#if defined(MCUBOOT_SHA512) + psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_512); +#elif defined(MCUBOOT_SIGN_EC384) psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_384); #else psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_256); @@ -108,7 +113,9 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, { size_t hash_length = 0; /* Assumes the output buffer is at least the expected size of the hash */ -#if defined(MCUBOOT_SIGN_EC384) +#if defined(MCUBOOT_SHA512) + return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_512), &hash_length); +#elif defined(MCUBOOT_SIGN_EC384) return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_384), &hash_length); #else return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &hash_length); diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 3e03f80dd..9ede800a2 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -96,6 +96,7 @@ struct flash_area; #define IMAGE_TLV_PUBKEY 0x02 /* public key */ #define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ #define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ +#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ #define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ #define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ #define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 81782edf2..5043d385a 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -368,6 +368,7 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_PUBKEY, IMAGE_TLV_SHA256, IMAGE_TLV_SHA384, + IMAGE_TLV_SHA512, IMAGE_TLV_RSA2048_PSS, IMAGE_TLV_ECDSA224, IMAGE_TLV_ECDSA_SIG, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 28f40bf52..8b35ab18c 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -27,6 +27,12 @@ config BOOT_USE_MBEDTLS help Use mbedTLS for crypto primitives. +config BOOT_USE_PSA_CRYPTO + bool + # Hidden option + help + Hidden option set if using PSA crypt for cryptography functionality + config BOOT_USE_TINYCRYPT bool # Hidden option @@ -70,6 +76,52 @@ config SINGLE_APPLICATION_SLOT uploading a new application overwrites the one that previously occupied the area. +config BOOT_IMG_HASH_ALG_SHA256_ALLOW + bool + help + Hidden option set by configurations that allow SHA256 + +config BOOT_IMG_HASH_ALG_SHA384_ALLOW + bool + help + Hidden option set by configurations that allow SHA384 + +config BOOT_IMG_HASH_ALG_SHA512_ALLOW + bool + depends on BOOT_USE_PSA_CRYPTO + help + Hidden option set by configurations that allow SHA512 + +choice BOOT_IMG_HASH_ALG + prompt "Selected image hash algorithm" + default BOOT_IMG_HASH_ALG_SHA256 if BOOT_IMG_HASH_ALG_SHA256_ALLOW + default BOOT_IMG_HASH_ALG_SHA384 if BOOT_IMG_HASH_ALG_SHA384_ALLOW + default BOOT_IMG_HASH_ALG_SHA512 if BOOT_IMG_HASH_ALG_SHA512_ALLOW + help + Hash algorithm used for image verification. Selection + here may be limited by other configurations, like for + example selected cryptographic signature. + +config BOOT_IMG_HASH_ALG_SHA256 + bool "SHA256" + depends on BOOT_IMG_HASH_ALG_SHA256_ALLOW + help + SHA256 algorithm + +config BOOT_IMG_HASH_ALG_SHA384 + bool "SHA384" + depends on BOOT_IMG_HASH_ALG_SHA384_ALLOW + help + SHA384 algorithm + +config BOOT_IMG_HASH_ALG_SHA512 + bool "SHA512" + depends on BOOT_IMG_HASH_ALG_SHA512_ALLOW + help + SHA512 algorithm + +endchoice # BOOT_IMG_HASH_ALG + choice BOOT_SIGNATURE_TYPE prompt "Signature type" default BOOT_SIGNATURE_TYPE_RSA @@ -77,12 +129,14 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" select BOOT_USE_TINYCRYPT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA bool "RSA signatures" select BOOT_USE_MBEDTLS select MBEDTLS select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_RSA_LEN @@ -94,6 +148,7 @@ endif config BOOT_SIGNATURE_TYPE_ECDSA_P256 bool "Elliptic curve digital signatures with curve P-256" select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION @@ -117,6 +172,7 @@ endif config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" select BOOT_ENCRYPTION_SUPPORT + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if BOOT_SIGNATURE_TYPE_ED25519 choice BOOT_ED25519_IMPLEMENTATION diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 824e83b75..9d58436d2 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -40,10 +40,20 @@ #define MCUBOOT_USE_TINYCRYPT #elif defined(CONFIG_BOOT_USE_CC310) #define MCUBOOT_USE_CC310 +#elif defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) +#define MCUBOOT_USE_PSA_CRYPTO #elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) #define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif +#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 +#define MCUBOOT_SHA512 +#endif + +#ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA256 +#define MCUBOOT_SHA256 +#endif + /* Zephyr, regardless of C library used, provides snprintf */ #define MCUBOOT_USE_SNPRINTF 1 diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 3de8357a6..53b19ef1d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -1,6 +1,6 @@ # Copyright 2018 Nordic Semiconductor ASA # Copyright 2017-2020 Linaro Limited -# Copyright 2019-2023 Arm Limited +# Copyright 2019-2024 Arm Limited # # SPDX-License-Identifier: Apache-2.0 # @@ -20,23 +20,27 @@ Image signing and management. """ -from . import version as versmod -from .boot_record import create_sw_component_data -import click -from enum import Enum -from intelhex import IntelHex import hashlib -import struct import os.path -from .keys import rsa, ecdsa, x25519 +import struct +from enum import Enum + +import click +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes, hmac from cryptography.hazmat.primitives.asymmetric import ec, padding from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.kdf.hkdf import HKDF from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes, hmac -from cryptography.exceptions import InvalidSignature +from intelhex import IntelHex + +from . import version as versmod, keys +from .boot_record import create_sw_component_data +from .keys import rsa, ecdsa, x25519 + +from collections import namedtuple IMAGE_MAGIC = 0x96f3b83d IMAGE_HEADER_SIZE = 32 @@ -63,6 +67,7 @@ 'PUBKEY': 0x02, 'SHA256': 0x10, 'SHA384': 0x11, + 'SHA512': 0x12, 'RSA2048': 0x20, 'ECDSASIG': 0x22, 'RSA3072': 0x23, @@ -90,10 +95,8 @@ } VerifyResult = Enum('VerifyResult', - """ - OK INVALID_MAGIC INVALID_TLV_INFO_MAGIC INVALID_HASH - INVALID_SIGNATURE - """) + ['OK', 'INVALID_MAGIC', 'INVALID_TLV_INFO_MAGIC', 'INVALID_HASH', 'INVALID_SIGNATURE', + 'KEY_MISMATCH']) def align_up(num, align): @@ -135,14 +138,101 @@ def get(self): return header + bytes(self.buf) -class Image(): +SHAAndAlgT = namedtuple('SHAAndAlgT', ['sha', 'alg']) + +TLV_SHA_TO_SHA_AND_ALG = { + TLV_VALUES['SHA256'] : SHAAndAlgT('256', hashlib.sha256), + TLV_VALUES['SHA384'] : SHAAndAlgT('384', hashlib.sha384), + TLV_VALUES['SHA512'] : SHAAndAlgT('512', hashlib.sha512), +} + + +USER_SHA_TO_ALG_AND_TLV = { + 'auto' : (hashlib.sha256, 'SHA256'), + '256' : (hashlib.sha256, 'SHA256'), + '384' : (hashlib.sha384, 'SHA384'), + '512' : (hashlib.sha512, 'SHA512') +} + + +def is_sha_tlv(tlv): + return tlv in TLV_SHA_TO_SHA_AND_ALG.keys() + + +def tlv_sha_to_sha(tlv): + return TLV_SHA_TO_SHA_AND_ALG[tlv].sha + + +# Auto selecting hash algorithm for type(key) +ALLOWED_KEY_SHA = { + keys.ECDSA384P1 : ['384'], + keys.ECDSA384P1Public : ['384'], + keys.ECDSA256P1 : ['256'], + keys.RSA : ['256'], + # This two are set to 256 for compatibility, the right would be 512 + keys.Ed25519 : ['256', '512'], + keys.X25519 : ['256', '512'] +} + +def key_and_user_sha_to_alg_and_tlv(key, user_sha): + """Matches key and user requested sha to sha alogrithm and TLV name. + + The returned tuple will contain hash functions and TVL name. + The function is designed to succeed or completely fail execution, + as providing incorrect pair here basically prevents doing + any more work. + """ + if key is None: + # If key is none, we allow whatever user has selected for sha + return USER_SHA_TO_ALG_AND_TLV[user_sha] + + # If key is not None, then we have to filter hash to only allowed + allowed = None + try: + allowed = ALLOWED_KEY_SHA[type(key)] + except KeyError: + raise click.UsageError("Colud not find allowed hash algorithms for {}" + .format(type(key))) + if user_sha == 'auto': + return USER_SHA_TO_ALG_AND_TLV[allowed[0]] + + if user_sha in allowed: + return USER_SHA_TO_ALG_AND_TLV[user_sha] + + raise click.UsageError("Key {} can not be used with --sha {}; allowed sha are one of {}" + .format(key.sig_type(), user_sha, allowed)) + + +def get_digest(tlv_type, hash_region): + sha = TLV_SHA_TO_SHA_AND_ALG[tlv_type].alg() + + sha.update(hash_region) + return sha.digest() + + +def tlv_matches_key_type(tlv_type, key): + """Check if provided key matches to TLV record in the image""" + try: + # We do not need the result here, and the key_and_user_sha_to_alg_and_tlv + # will either succeed finding match or rise exception, so on success we + # return True, on exception we return False. + _, _ = key_and_user_sha_to_alg_and_tlv(key, tlv_sha_to_sha(tlv_type)) + return True + except: + pass + + return False + + +class Image: def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, pad_header=False, pad=False, confirm=False, align=1, slot_size=0, max_sectors=DEFAULT_MAX_SECTORS, overwrite_only=False, endian="little", load_addr=0, rom_fixed=None, erased_val=None, save_enctlv=False, - security_counter=None, max_align=None): + security_counter=None, max_align=None, + non_bootable=False): if load_addr and rom_fixed: raise click.UsageError("Can not set rom_fixed and load_addr at the same time") @@ -166,6 +256,7 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, self.save_enctlv = save_enctlv self.enctlv_len = 0 self.max_align = max(DEFAULT_MAX_ALIGN, align) if max_align is None else int(max_align) + self.non_bootable = non_bootable if self.max_align == DEFAULT_MAX_ALIGN: self.boot_magic = bytes([ @@ -178,9 +269,9 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, msb = (self.max_align & 0xff00) >> 8 align = bytes([msb, lsb]) if self.endian == "big" else bytes([lsb, msb]) self.boot_magic = align + bytes([0x2d, 0xe1, - 0x5d, 0x29, 0x41, 0x0b, - 0x8d, 0x77, 0x67, 0x9c, - 0x11, 0x0f, 0x1f, 0x8a, ]) + 0x5d, 0x29, 0x41, 0x0b, + 0x8d, 0x77, 0x67, 0x9c, + 0x11, 0x0f, 0x1f, 0x8a, ]) if security_counter == 'auto': # Security counter has not been explicitly provided, @@ -317,18 +408,13 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None): + fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): self.enckey = enckey - # Check what hashing algorithm should be used - if (key is not None and isinstance(key, ecdsa.ECDSA384P1) or - pub_key is not None and isinstance(pub_key, - ecdsa.ECDSA384P1Public)): - hash_algorithm = hashlib.sha384 - hash_tlv = "SHA384" - else: - hash_algorithm = hashlib.sha256 - hash_tlv = "SHA256" + # key decides on sha, then pub_key; of both are none default is used + check_key = key if key is not None else pub_key + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) + # Calculate the hash of the public key if key is not None: pub = key.get_public_bytes() @@ -430,13 +516,13 @@ def create(self, key, public_key_format, enckey, dependencies=None, if dependencies is not None: for i in range(dependencies_num): payload = struct.pack( - e + 'B3x'+'BBHI', - int(dependencies[DEP_IMAGES_KEY][i]), - dependencies[DEP_VERSIONS_KEY][i].major, - dependencies[DEP_VERSIONS_KEY][i].minor, - dependencies[DEP_VERSIONS_KEY][i].revision, - dependencies[DEP_VERSIONS_KEY][i].build - ) + e + 'B3x' + 'BBHI', + int(dependencies[DEP_IMAGES_KEY][i]), + dependencies[DEP_VERSIONS_KEY][i].major, + dependencies[DEP_VERSIONS_KEY][i].minor, + dependencies[DEP_VERSIONS_KEY][i].revision, + dependencies[DEP_VERSIONS_KEY][i].build + ) prot_tlv.add('DEPENDENCY', payload) if custom_tlvs is not None: @@ -448,11 +534,14 @@ def create(self, key, public_key_format, enckey, dependencies=None, tlv = TLV(self.endian) - # Note that ecdsa wants to do the hashing itself, which means - # we get to hash it twice. + # These signature is done over sha of image. In case of + # EC signatures so called Pure algorithm, designated to be run + # over entire message is used with sha of image as message, + # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512. sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() + message = digest; tlv.add(hash_tlv, digest) if vector_to_sign == 'payload': @@ -481,7 +570,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, sig = key.sign(bytes(self.payload)) else: print(os.path.basename(__file__) + ": sign the digest") - sig = key.sign_digest(digest) + sig = key.sign_digest(message) tlv.add(key.sig_tlv(), sig) self.signature = sig elif fixed_sig is not None and key is None: @@ -551,6 +640,8 @@ def add_header(self, enckey, protected_tlv_size, aes_length=128): flags |= IMAGE_F['RAM_LOAD'] if self.rom_fixed: flags |= IMAGE_F['ROM_FIXED'] + if self.non_bootable: + flags |= IMAGE_F['NON_BOOTABLE'] e = STRUCT_ENDIAN_DICT[self.endian] fmt = (e + @@ -640,42 +731,37 @@ def verify(imgfile, key): return VerifyResult.INVALID_MAGIC, None, None tlv_off = header_size + img_size - tlv_info = b[tlv_off:tlv_off+TLV_INFO_SIZE] + tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] magic, tlv_tot = struct.unpack('HH', tlv_info) if magic == TLV_PROT_INFO_MAGIC: tlv_off += tlv_tot - tlv_info = b[tlv_off:tlv_off+TLV_INFO_SIZE] + tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] magic, tlv_tot = struct.unpack('HH', tlv_info) if magic != TLV_INFO_MAGIC: return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None - if isinstance(key, ecdsa.ECDSA384P1Public): - sha = hashlib.sha384() - hash_tlv = "SHA384" - else: - sha = hashlib.sha256() - hash_tlv = "SHA256" - prot_tlv_size = tlv_off - sha.update(b[:prot_tlv_size]) - digest = sha.digest() - + hash_region = b[:prot_tlv_size] + digest = None tlv_end = tlv_off + tlv_tot tlv_off += TLV_INFO_SIZE # skip tlv info while tlv_off < tlv_end: - tlv = b[tlv_off:tlv_off+TLV_SIZE] + tlv = b[tlv_off:tlv_off + TLV_SIZE] tlv_type, _, tlv_len = struct.unpack('BBH', tlv) - if tlv_type == TLV_VALUES[hash_tlv]: + if is_sha_tlv(tlv_type): + if not tlv_matches_key_type(tlv_type, key): + return VerifyResult.KEY_MISMATCH, None, None off = tlv_off + TLV_SIZE - if digest == b[off:off+tlv_len]: + digest = get_digest(tlv_type, hash_region) + if digest == b[off:off + tlv_len]: if key is None: return VerifyResult.OK, version, digest else: return VerifyResult.INVALID_HASH, None, None elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: off = tlv_off + TLV_SIZE - tlv_sig = b[off:off+tlv_len] + tlv_sig = b[off:off + tlv_len] payload = b[:prot_tlv_size] try: if hasattr(key, 'verify'): diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index e24c9a087..848fd3110 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -72,6 +72,7 @@ def gen_x25519(keyfile, passwd): 'x25519': gen_x25519, } valid_formats = ['openssl', 'pkcs8'] +valid_sha = [ 'auto', '256', '384', '512' ] def load_signature(sigfile): @@ -228,6 +229,8 @@ def verify(key, imgfile): print("Image has an invalid hash") elif ret == image.VerifyResult.INVALID_SIGNATURE: print("No signature found for the given key") + elif ret == image.VerifyResult.KEY_MISMATCH: + print("Key type does not match TLV record") else: print("Unknown return code: {}".format(ret)) sys.exit(1) @@ -312,6 +315,8 @@ def convert(self, value, param, ctx): @click.argument('outfile') @click.argument('infile') +@click.option('--non-bootable', default=False, is_flag=True, + help='Mark the image as non-bootable.') @click.option('--custom-tlv', required=False, nargs=2, default=[], multiple=True, metavar='[tag] [value]', help='Custom TLV that will be placed into protected area. ' @@ -397,6 +402,9 @@ def convert(self, value, param, ctx): @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') +@click.option('--sha', 'user_sha', type=click.Choice(valid_sha), default='auto', + help='selected sha algorithm to use; defaults to "auto" which is 256 if ' + 'no cryptographic signature is used, or default for signature type') @click.option('--vector-to-sign', type=click.Choice(['payload', 'digest']), help='send to OUTFILE the payload or payload''s digest instead ' 'of complied image. These data can be used for external image ' @@ -409,7 +417,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, - fix_sig_pubkey, sig_out, vector_to_sign): + fix_sig_pubkey, sig_out, user_sha, vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -421,7 +429,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, max_sectors=max_sectors, overwrite_only=overwrite_only, endian=endian, load_addr=load_addr, rom_fixed=rom_fixed, erased_val=erased_val, save_enctlv=save_enctlv, - security_counter=security_counter, max_align=max_align) + security_counter=security_counter, max_align=max_align, + non_bootable=non_bootable) img.load(infile) key = load_key(key) if key else None enckey = load_key(encrypt) if encrypt else None @@ -476,7 +485,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign) + pub_key, vector_to_sign, user_sha) img.save(outfile, hex_addr) if sig_out is not None: