]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
binman: add sign option for binman
authorIvan Mikhaylov <fr0st61te@gmail.com>
Wed, 8 Mar 2023 01:13:39 +0000 (01:13 +0000)
committerSimon Glass <sjg@chromium.org>
Tue, 14 Mar 2023 22:08:51 +0000 (16:08 -0600)
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@gmail.com>
common/main.c
tools/binman/cmdline.py
tools/binman/control.py
tools/binman/etype/fit.py
tools/binman/etype/section.py

index 682f3359ea382088ac6a682fdeff8a09303a2652..7c70de2e59a8e2d928c74e1588245884d62e04b6 100644 (file)
@@ -13,6 +13,7 @@
 #include <command.h>
 #include <console.h>
 #include <env.h>
+#include <fdtdec.h>
 #include <init.h>
 #include <net.h>
 #include <version_string.h>
index 1b7bbe80cda61bbdcda69fb5420dc47afebf8394..4b875a9dcda35eb38e7eaa413796cdcad21487d9 100644 (file)
@@ -176,6 +176,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)')
+
     if HAS_TESTS:
         test_parser = subparsers.add_parser('test', help='Run tests')
         test_parser.add_argument('-P', '--processes', type=int,
index 2f2b4893b7ef54bd24878a3aad518c4a36c7a812..cf2c91f622ac94a25ecc2e7c8e7e6dbe9084d924 100644 (file)
@@ -448,6 +448,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
@@ -660,7 +683,7 @@ def Binman(args):
     tools.set_tool_paths(tool_paths or None)
     bintool.Bintool.set_tool_dir(args.tooldir)
 
-    if args.cmd in ['ls', 'extract', 'replace', 'tool']:
+    if args.cmd in ['ls', 'extract', 'replace', 'tool', 'sign']:
         try:
             tout.init(args.verbosity)
             if args.cmd == 'replace':
@@ -679,6 +702,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':
                 if args.list:
                     bintool.Bintool.list_all()
index 03fe88e7a6ce89c5f48adc6995fe855f4fa1c9ce..3aea9865bf4498fd8870c2d65be6567c3b5cdb29 100644 (file)
@@ -835,3 +835,21 @@ class Entry_fit(Entry_section):
 
     def CheckEntries(self):
         pass
+
+    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)
index c36edd13508bcec51f31c4fddd7e2f87cd17c142..e87009d6ce3e546f20cc859724b24319563b7b9d 100644 (file)
@@ -1014,3 +1014,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')