diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 627cc6c0..749b6da1 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -305,7 +305,7 @@ class Image(): return cipherkey, ciphermac, pubk def create(self, key, public_key_format, enckey, dependencies=None, - sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False): + sw_type=None, custom_tlvs=None, encrypt_keylen=128, clear=False, fixed_sig=None, pub_key=None): self.enckey = enckey # Calculate the hash of the public key @@ -314,6 +314,11 @@ class Image(): sha = hashlib.sha256() sha.update(pub) pubbytes = sha.digest() + elif pub_key is not None: + pub = pub_key.get_public_bytes() + sha = hashlib.sha256() + sha.update(pub) + pubbytes = sha.digest() else: pubbytes = bytes(hashlib.sha256().digest_size) @@ -428,7 +433,7 @@ class Image(): tlv.add('SHA256', digest) - if key is not None: + if key is not None and fixed_sig is None: if public_key_format == 'hash': tlv.add('KEYHASH', pubbytes) else: @@ -442,6 +447,14 @@ class Image(): else: sig = key.sign_digest(digest) tlv.add(key.sig_tlv(), sig) + elif fixed_sig is not None and key is None: + if public_key_format == 'hash': + tlv.add('KEYHASH', pubbytes) + else: + tlv.add('PUBKEY', pub) + tlv.add(pub_key.sig_tlv(), fixed_sig['value']) + else: + raise click.UsageError("Can not sign using key and provide fixed-signature at the same time") # At this point the image was hashed + signed, we can remove the # protected TLVs from the payload (will be re-added later) @@ -486,6 +499,9 @@ class Image(): self.check_trailer() + def get_signature(self): + return self.signature + def add_header(self, enckey, protected_tlv_size, aes_length=128): """Install the image header.""" diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index fc56ee49..f2e246ea 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -22,6 +22,7 @@ import click import getpass import imgtool.keys as keys import sys +import base64 from imgtool import image, imgtool_version from imgtool.version import decode_version from .keys import ( @@ -68,6 +69,10 @@ keygens = { 'x25519': gen_x25519, } +def load_signature(sigfile): + with open(sigfile, 'rb') as f: + signature = base64.b64decode(f.read()) + return signature def load_key(keyfile): # TODO: better handling of invalid pass-phrase @@ -303,6 +308,11 @@ class BasedIntParamType(click.ParamType): 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('--fix-sig', metavar='filename', + help='fixed signature for the image. It will be used instead of' + 'the signature calculated using the public key') +@click.option('--fix-sig-pubkey', metavar='filename', + help='public key relevant to fixed signature') @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''') @@ -310,7 +320,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, pad_header, slot_size, pad, confirm, max_sectors, overwrite_only, 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): + boot_record, custom_tlv, rom_fixed, max_align, clear, fix_sig, + fix_sig_pubkey): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -356,8 +367,25 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, else: custom_tlvs[tag] = value.encode('utf-8') + # Allow signature calculated externally. + raw_signature = load_signature(fix_sig) if fix_sig else None + + baked_signature = None + pub_key = None + + if raw_signature is not None: + if fix_sig_pubkey is None: + raise click.UsageError( + 'public key of the fixed signature is not specified') + + pub_key = load_key(fix_sig_pubkey) + + baked_signature = { + 'value' : raw_signature + } + img.create(key, public_key_format, enckey, dependencies, boot_record, - custom_tlvs, int(encrypt_keylen), clear) + custom_tlvs, int(encrypt_keylen), clear, baked_signature, pub_key) img.save(outfile, hex_addr)