public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Ivan Mikhaylov <fr0st61te@gmail.com>
To: Simon Glass <sjg@chromium.org>, Jan Kiszka <jan.kiszka@siemens.com>
Cc: u-boot@lists.denx.de, Ivan Mikhaylov <fr0st61te@gmail.com>
Subject: [PATCH v2 2/5] binman: add sign option for binman
Date: Wed,  8 Mar 2023 01:13:39 +0000	[thread overview]
Message-ID: <20230308011342.21992-3-fr0st61te@gmail.com> (raw)
In-Reply-To: <20230308011342.21992-1-fr0st61te@gmail.com>

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>
---
 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


  parent reply	other threads:[~2023-03-08 13:21 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-08  1:13 [PATCH v2 0/5] Introduce new sign binman's option Ivan Mikhaylov
2023-03-08  1:13 ` [PATCH v2 1/5] binman: add documentation for binman sign option Ivan Mikhaylov
2023-03-11  1:47   ` Simon Glass
2023-03-12 17:36     ` Simon Glass
2023-03-08  1:13 ` Ivan Mikhaylov [this message]
2023-03-11  1:37   ` [PATCH v2 2/5] binman: add sign option for binman Simon Glass
2023-03-11  1:47     ` Simon Glass
2023-03-12 17:36       ` Simon Glass
2023-03-08  1:13 ` [PATCH v2 3/5] binman: add tests for sign option Ivan Mikhaylov
2023-03-11  1:47   ` Simon Glass
2023-03-11  1:48     ` Simon Glass
2023-03-12 17:36       ` Simon Glass
2023-03-08  1:13 ` [PATCH v2 4/5] tools: add fdt_add_pubkey Ivan Mikhaylov
2023-03-11  1:47   ` Simon Glass
2023-03-08  1:13 ` [PATCH v2 5/5] test_vboot.py: include test of fdt_add_pubkey tool Ivan Mikhaylov
2023-03-11  1:46   ` Simon Glass
2023-03-16  4:17     ` Ivan Mikhaylov
2023-03-16 13:59       ` Simon Glass
2023-03-16 17:45         ` Ivan Mikhaylov
2023-03-16 21:49           ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230308011342.21992-3-fr0st61te@gmail.com \
    --to=fr0st61te@gmail.com \
    --cc=jan.kiszka@siemens.com \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox