binman: add sign option for binman
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>
This commit is contained in:
parent
0f40e23fd2
commit
4023dc9c95
5 changed files with 62 additions and 1 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
#include <env.h>
|
#include <env.h>
|
||||||
|
#include <fdtdec.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <version_string.h>
|
#include <version_string.h>
|
||||||
|
|
|
@ -176,6 +176,19 @@ controlled by a description in the board device tree.'''
|
||||||
replace_parser.add_argument('paths', type=str, nargs='*',
|
replace_parser.add_argument('paths', type=str, nargs='*',
|
||||||
help='Paths within file to replace (wildcard)')
|
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:
|
if HAS_TESTS:
|
||||||
test_parser = subparsers.add_parser('test', help='Run tests')
|
test_parser = subparsers.add_parser('test', help='Run tests')
|
||||||
test_parser.add_argument('-P', '--processes', type=int,
|
test_parser.add_argument('-P', '--processes', type=int,
|
||||||
|
|
|
@ -448,6 +448,29 @@ def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
|
||||||
AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
|
AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
|
||||||
return image
|
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):
|
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
|
||||||
"""Prepare the images to be processed and select the device tree
|
"""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)
|
tools.set_tool_paths(tool_paths or None)
|
||||||
bintool.Bintool.set_tool_dir(args.tooldir)
|
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:
|
try:
|
||||||
tout.init(args.verbosity)
|
tout.init(args.verbosity)
|
||||||
if args.cmd == 'replace':
|
if args.cmd == 'replace':
|
||||||
|
@ -679,6 +702,9 @@ def Binman(args):
|
||||||
do_compress=not args.compressed,
|
do_compress=not args.compressed,
|
||||||
allow_resize=not args.fix_size, write_map=args.map)
|
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.cmd == 'tool':
|
||||||
if args.list:
|
if args.list:
|
||||||
bintool.Bintool.list_all()
|
bintool.Bintool.list_all()
|
||||||
|
|
|
@ -835,3 +835,21 @@ class Entry_fit(Entry_section):
|
||||||
|
|
||||||
def CheckEntries(self):
|
def CheckEntries(self):
|
||||||
pass
|
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)
|
||||||
|
|
|
@ -1014,3 +1014,6 @@ class Entry_section(Entry):
|
||||||
for entry in entries.values():
|
for entry in entries.values():
|
||||||
return entry.read_elf_segments()
|
return entry.read_elf_segments()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def UpdateSignatures(self, privatekey_fname, algo, input_fname):
|
||||||
|
self.Raise('Updating signatures is not supported with this entry type')
|
||||||
|
|
Loading…
Reference in a new issue