[PATCH v2 2/5] binman: add sign option for binman
Ivan Mikhaylov
fr0st61te at gmail.com
Wed Mar 8 02:13:39 CET 2023
Introduce proof of concept for binman's new option which provides sign
and replace FIT containers in binary images.
Usage as example:
from:
mkimage -G privateky -r -o sha256,rsa4096 -F fit
binman replace -i flash.bin -f fit.fit fit
to:
binman sign -i flash.bin -k privatekey -a sha256,rsa4096 -f fit.fit fit
and to this one if it's need to be extracted, signed with key and put it
back in image:
binman sign -i flash.bin -k privatekey -a sha256,rsa4096 fit
Signed-off-by: Ivan Mikhaylov <fr0st61te at gmail.com>
---
tools/binman/cmdline.py | 13 +++++++++++++
tools/binman/control.py | 29 ++++++++++++++++++++++++++++-
tools/binman/etype/fit.py | 18 ++++++++++++++++++
tools/binman/etype/section.py | 3 +++
4 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
index 986d6f1a31..e2961ed11f 100644
--- a/tools/binman/cmdline.py
+++ b/tools/binman/cmdline.py
@@ -163,6 +163,19 @@ controlled by a description in the board device tree.'''
replace_parser.add_argument('paths', type=str, nargs='*',
help='Paths within file to replace (wildcard)')
+ sign_parser = subparsers.add_parser('sign',
+ help='Sign entries in image')
+ sign_parser.add_argument('-a', '--algo', type=str, required=True,
+ help='Hash algorithm e.g. sha256,rsa4096')
+ sign_parser.add_argument('-f', '--file', type=str, required=False,
+ help='Input filename to sign')
+ sign_parser.add_argument('-i', '--image', type=str, required=True,
+ help='Image filename to update')
+ sign_parser.add_argument('-k', '--key', type=str, required=True,
+ help='Private key file for signing')
+ sign_parser.add_argument('paths', type=str, nargs='*',
+ help='Paths within file to sign (wildcard)')
+
test_parser = subparsers.add_parser('test', help='Run tests')
test_parser.add_argument('-P', '--processes', type=int,
help='set number of processes to use for running tests')
diff --git a/tools/binman/control.py b/tools/binman/control.py
index e64740094f..9ebd73913a 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -20,6 +20,7 @@ from patman import command
from binman import elf
from binman import entry
from patman import tout
+from patman import tools
# These are imported if needed since they import libfdt
state = None
@@ -445,6 +446,29 @@ def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
return image
+def SignEntries(image_fname, input_fname, privatekey_fname, algo, entry_paths,
+ write_map=False):
+ """Sign and replace the data from one or more entries from input files
+
+ Args:
+ image_fname: Image filename to process
+ input_fname: Single input filename to use if replacing one file, None
+ otherwise
+ algo: Hashing algorithm
+ entry_paths: List of entry paths to sign
+ privatekey_fname: Private key filename
+ write_map (bool): True to write the map file
+ """
+ image_fname = os.path.abspath(image_fname)
+ image = Image.FromFile(image_fname)
+
+ BeforeReplace(image, allow_resize=True)
+
+ for entry_path in entry_paths:
+ entry = image.FindEntryPath(entry_path)
+ entry.UpdateSignatures(privatekey_fname, algo, input_fname)
+
+ AfterReplace(image, allow_resize=True, write_map=write_map)
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
"""Prepare the images to be processed and select the device tree
@@ -650,7 +674,7 @@ def Binman(args):
from binman.image import Image
from binman import state
- if args.cmd in ['ls', 'extract', 'replace', 'tool']:
+ if args.cmd in ['ls', 'extract', 'replace', 'tool', 'sign']:
try:
tout.init(args.verbosity)
tools.prepare_output_dir(None)
@@ -666,6 +690,9 @@ def Binman(args):
do_compress=not args.compressed,
allow_resize=not args.fix_size, write_map=args.map)
+ if args.cmd == 'sign':
+ SignEntries(args.image, args.file, args.key, args.algo, args.paths)
+
if args.cmd == 'tool':
tools.set_tool_paths(args.toolpath)
if args.list:
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index cd2943533c..c0451fe765 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -828,3 +828,21 @@ class Entry_fit(Entry_section):
# missing
for entry in self._priv_entries.values():
entry.CheckMissing(missing_list)
+
+ def UpdateSignatures(self, privatekey_fname, algo, input_fname):
+ uniq = self.GetUniqueName()
+ args = [ '-G', privatekey_fname, '-r', '-o', algo, '-F' ]
+ if input_fname:
+ fname = input_fname
+ else:
+ fname = tools.get_output_filename('%s.fit' % uniq)
+ tools.write_file(fname, self.GetData())
+ args.append(fname)
+
+ if self.mkimage.run_cmd(*args) is None:
+ # Bintool is missing; just use empty data as the output
+ self.record_missing_bintool(self.mkimage)
+ return
+
+ data = tools.read_file(fname)
+ self.WriteData(data)
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 57b91ff726..4d0152e194 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -1000,3 +1000,6 @@ class Entry_section(Entry):
for entry in entries.values():
return entry.read_elf_segments()
return None
+
+ def UpdateSignatures(self, privatekey_fname, algo, input_fname):
+ self.Raise('Updating signatures is not supported with this entry type')
--
2.39.1
More information about the U-Boot
mailing list