1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0-only 3# 4# Public key to dtsi converter. 5# 6# Copyright (c) Siemens AG, 2022 7# 8 9from argparse import ArgumentParser, FileType 10from os.path import basename, splitext 11from Cryptodome.PublicKey import RSA 12from Cryptodome.Util.number import inverse 13 14def int_to_bytestr(n, length=None): 15 if not length: 16 length = (n.bit_length() + 7) // 8 17 byte_array = n.to_bytes(length, 'big') 18 return ' '.join(['{:02x}'.format(byte) for byte in byte_array]) 19 20ap = ArgumentParser(description='Public key to dtsi converter') 21 22ap.add_argument('--hash', '-H', default='sha256', 23 help='hash to be used with key (default: sha256)') 24ap.add_argument('--required-conf', '-c', action='store_true', 25 help='mark key required for configuration') 26ap.add_argument('--required-image', '-i', action='store_true', 27 help='mark key required for image') 28ap.add_argument('--spl', '-s', action='store_true', 29 help='mark key for usage in SPL') 30ap.add_argument('key_file', metavar='KEY_FILE', type=FileType('r'), 31 help='key file (formats: X.509, PKCS#1, OpenSSH)') 32ap.add_argument('dtsi_file', metavar='DTSI_FILE', type=FileType('w'), 33 help='dtsi output file') 34 35args = ap.parse_args() 36 37key_name, _ = splitext(basename(args.key_file.name)) 38 39key_data = args.key_file.read() 40key = RSA.importKey(key_data) 41 42r_squared = (2**key.size_in_bits())**2 % key.n 43n0_inverse = 2**32 - inverse(key.n, 2**32) 44 45out = args.dtsi_file 46out.write('/ {\n') 47out.write('\tsignature {\n') 48out.write('\t\tkey-{} {{\n'.format(key_name)) 49out.write('\t\t\tkey-name-hint = "{}";\n'.format(key_name)) 50out.write('\t\t\talgo = "{},rsa{}";\n'.format(args.hash, key.size_in_bits())) 51out.write('\t\t\trsa,num-bits = <{}>;\n'.format(key.size_in_bits())) 52out.write('\t\t\trsa,modulus = [{}];\n'.format(int_to_bytestr(key.n))) 53out.write('\t\t\trsa,exponent = [{}];\n'.format(int_to_bytestr(key.e, 8))) 54out.write('\t\t\trsa,r-squared = [{}];\n'.format(int_to_bytestr(r_squared))) 55out.write('\t\t\trsa,n0-inverse = <0x{:x}>;\n'.format(n0_inverse)) 56if args.required_conf: 57 out.write('\t\t\trequired = "conf";\n') 58elif args.required_image: 59 out.write('\t\t\trequired = "image";\n') 60if args.spl: 61 out.write('\t\t\tu-boot,dm-spl;\n') 62out.write('\t\t};\n') 63out.write('\t};\n') 64out.write('};\n') 65