blob: 9420d2ba99758582a858974befcd513281322e9c [file] [log] [blame]
Tamas Banf70ef8c2017-12-19 15:35:09 +00001#! /usr/bin/env python3
2#
3# Copyright 2017 Linaro Limited
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import argparse
18from imgtool import keys
19from imgtool import image
20from imgtool import version
21import sys
22
23def gen_rsa2048(args):
24 keys.RSA2048.generate().export_private(args.key)
Tamas Banf70ef8c2017-12-19 15:35:09 +000025
26keygens = {
Tamas Ban581034a2017-12-19 19:54:37 +000027 'rsa-2048': gen_rsa2048, }
Tamas Banf70ef8c2017-12-19 15:35:09 +000028
29def do_keygen(args):
30 if args.type not in keygens:
31 msg = "Unexpected key type: {}".format(args.type)
32 raise argparse.ArgumentTypeError(msg)
33 keygens[args.type](args)
34
35def do_getpub(args):
36 key = keys.load(args.key)
37 if args.lang == 'c':
38 key.emit_c()
Tamas Banf70ef8c2017-12-19 15:35:09 +000039 else:
Tamas Ban581034a2017-12-19 19:54:37 +000040 msg = "Unsupported language, valid are: c"
Tamas Banf70ef8c2017-12-19 15:35:09 +000041 raise argparse.ArgumentTypeError(msg)
42
43def do_sign(args):
44 if args.rsa_pkcs1_15:
45 keys.sign_rsa_pss = False
46 img = image.Image.load(args.infile, version=args.version,
47 header_size=args.header_size,
48 included_header=args.included_header,
49 pad=args.pad)
50 key = keys.load(args.key) if args.key else None
51 img.sign(key)
52
53 if args.pad:
54 img.pad_to(args.pad, args.align)
55
56 img.save(args.outfile)
57
58subcmds = {
59 'keygen': do_keygen,
60 'getpub': do_getpub,
61 'sign': do_sign, }
62
63def alignment_value(text):
64 value = int(text)
65 if value not in [1, 2, 4, 8]:
66 msg = "{} must be one of 1, 2, 4 or 8".format(value)
67 raise argparse.ArgumentTypeError(msg)
68 return value
69
70def intparse(text):
71 """Parse a command line argument as an integer.
72
73 Accepts 0x and other prefixes to allow other bases to be used."""
74 return int(text, 0)
75
76def args():
77 parser = argparse.ArgumentParser()
78 subs = parser.add_subparsers(help='subcommand help', dest='subcmd')
79
80 keygenp = subs.add_parser('keygen', help='Generate pub/private keypair')
81 keygenp.add_argument('-k', '--key', metavar='filename', required=True)
82 keygenp.add_argument('-t', '--type', metavar='type',
83 choices=keygens.keys(), required=True)
84
85 getpub = subs.add_parser('getpub', help='Get public key from keypair')
86 getpub.add_argument('-k', '--key', metavar='filename', required=True)
87 getpub.add_argument('-l', '--lang', metavar='lang', default='c')
88
89 sign = subs.add_parser('sign', help='Sign an image with a private key')
90 sign.add_argument('-k', '--key', metavar='filename')
91 sign.add_argument("--align", type=alignment_value, required=True)
92 sign.add_argument("-v", "--version", type=version.decode_version, required=True)
93 sign.add_argument("-H", "--header-size", type=intparse, required=True)
94 sign.add_argument("--included-header", default=False, action='store_true',
95 help='Image has gap for header')
96 sign.add_argument("--pad", type=intparse,
97 help='Pad image to this many bytes, adding trailer magic')
98 sign.add_argument("--rsa-pkcs1-15", help='Use old PKCS#1 v1.5 signature algorithm',
99 default=False, action='store_true')
100 sign.add_argument("infile")
101 sign.add_argument("outfile")
102
103 args = parser.parse_args()
104 if args.subcmd is None:
105 print('Must specify a subcommand', file=sys.stderr)
106 sys.exit(1)
107
108 subcmds[args.subcmd](args)
109
110if __name__ == '__main__':
111 args()