blob: fb09f969a8fe2c8fff793c2ae3a5ee96e1b1a68d [file] [log] [blame]
David Brown23f91ad2017-05-16 11:38:17 -06001#! /usr/bin/env python3
2
3import argparse
4from imgtool import keys
5from imgtool import image
6from imgtool import version
7import sys
8
9def gen_rsa2048(args):
David Brown4c036152017-06-07 09:10:54 -060010 keys.RSA2048.generate().export_private(args.key)
David Brown23f91ad2017-05-16 11:38:17 -060011def gen_ecdsa_p256(args):
David Brown4c036152017-06-07 09:10:54 -060012 keys.ecdsa256p1.generate().export_private(args.key)
David Brown23f91ad2017-05-16 11:38:17 -060013def gen_ecdsa_p224(args):
14 print("TODO: p-224 not yet implemented")
15
16keygens = {
17 'rsa-2048': gen_rsa2048,
18 'ecdsa-p256': gen_ecdsa_p256,
19 'ecdsa-p224': gen_ecdsa_p224, }
20
21def do_keygen(args):
22 if args.type not in keygens:
23 msg = "Unexpected key type: {}".format(args.type)
24 raise argparse.ArgumentTypeError(msg)
25 keygens[args.type](args)
26
27def do_getpub(args):
28 key = keys.load(args.key)
29 key.emit_c()
30
31def do_sign(args):
32 align = args.align
David Brown07916c32017-05-31 13:38:31 -060033 if args.rsa_pkcs1_15:
34 keys.sign_rsa_pss = False
David Brown23f91ad2017-05-16 11:38:17 -060035 img = image.Image.load(args.infile, version=args.version,
36 header_size=args.header_size,
37 pad=args.pad)
38 key = keys.load(args.key)
39 img.sign(key)
40
41 if args.pad:
42 img.pad_to(args.pad, args.align)
43
44 img.save(args.outfile)
45
46subcmds = {
47 'keygen': do_keygen,
48 'getpub': do_getpub,
49 'sign': do_sign, }
50
51def alignment_value(text):
52 value = int(text)
53 if value not in [1, 2, 4, 8]:
54 msg = "{} must be one of 1, 2, 4 or 8".format(value)
55 raise argparse.ArgumentTypeError(msg)
56 return value
57
58def intparse(text):
59 """Parse a command line argument as an integer.
60
61 Accepts 0x and other prefixes to allow other bases to be used."""
62 return int(text, 0)
63
64def args():
65 parser = argparse.ArgumentParser()
66 subs = parser.add_subparsers(help='subcommand help', dest='subcmd')
67
68 keygenp = subs.add_parser('keygen', help='Generate pub/private keypair')
69 keygenp.add_argument('-k', '--key', metavar='filename', required=True)
70 keygenp.add_argument('-t', '--type', metavar='type',
71 choices=['rsa-2048', 'ecdsa-p224', 'ecdsa-p256'],
72 required=True)
73
74 getpub = subs.add_parser('getpub', help='Get public key from keypair')
75 getpub.add_argument('-k', '--key', metavar='filename', required=True)
76
77 sign = subs.add_parser('sign', help='Sign an image with a private key')
78 sign.add_argument('-k', '--key', metavar='filename', required=True)
79 sign.add_argument("--align", type=alignment_value, required=True)
80 sign.add_argument("-v", "--version", type=version.decode_version, required=True)
81 sign.add_argument("-H", "--header-size", type=intparse, required=True)
82 sign.add_argument("--pad", type=intparse,
83 help='Pad image to this many bytes, adding trailer magic')
David Brown07916c32017-05-31 13:38:31 -060084 sign.add_argument("--rsa-pkcs1-15", help='Use old PKCS#1 v1.5 signature algorithm',
85 default=False, action='store_true')
David Brown23f91ad2017-05-16 11:38:17 -060086 sign.add_argument("infile")
87 sign.add_argument("outfile")
88
89 args = parser.parse_args()
90 if args.subcmd is None:
91 print('Must specify a subcommand', file=sys.stderr)
92 sys.exit(1)
93
94 subcmds[args.subcmd](args)
95
96if __name__ == '__main__':
97 args()