Commit 4d7adfd364af80427ac7694baa5ea4233f578948
1 parent
6043ad0d
tools: Add rpi-bootloader-key-convert
Add a Python utility script to converts RSA public keys from PEM format to the binary format required by the bootloader and vice-versa.
Showing
1 changed file
with
49 additions
and
0 deletions
tools/rpi-bootloader-key-convert
0 → 100755
| 1 | +#!/usr/bin/env python3 | |
| 2 | + | |
| 3 | +import argparse | |
| 4 | +import struct | |
| 5 | +import sys | |
| 6 | + | |
| 7 | +from Cryptodome.PublicKey import RSA | |
| 8 | + | |
| 9 | +def bintopem(infile, outf): | |
| 10 | + f = open(infile, 'rb') | |
| 11 | + arr = f.read(264) | |
| 12 | + | |
| 13 | + n = int.from_bytes(struct.unpack_from("256B", arr, 0), 'little') | |
| 14 | + e = struct.unpack_from("<Q", arr, 256)[0] | |
| 15 | + pubkey = RSA.construct((n, e)) | |
| 16 | + outf.write(pubkey.exportKey()) | |
| 17 | + | |
| 18 | +def pemtobin(infile, outf): | |
| 19 | + key = RSA.importKey(open(infile, 'r').read()) | |
| 20 | + | |
| 21 | + if key.size_in_bits() != 2048: | |
| 22 | + raise Exception("RSA key size must be 2048") | |
| 23 | + | |
| 24 | + # Extract the public key componenet n,e and store as little endian | |
| 25 | + outf.write(key.n.to_bytes(256, byteorder='little')) | |
| 26 | + outf.write(key.e.to_bytes(8, byteorder='little')) | |
| 27 | + | |
| 28 | +def main(): | |
| 29 | + parser = argparse.ArgumentParser('Converts RSA keys between PEM format and the raw binary format used by the Raspberry Pi 4 bootloader') | |
| 30 | + parser.add_argument('input', nargs='+') | |
| 31 | + parser.add_argument('--inform', default="pem") | |
| 32 | + parser.add_argument('--output', required=False) | |
| 33 | + | |
| 34 | + args = parser.parse_args() | |
| 35 | + | |
| 36 | + if args.output: | |
| 37 | + outf = open(args.output, 'wb') | |
| 38 | + else: | |
| 39 | + outf = sys.stdout.buffer | |
| 40 | + | |
| 41 | + if args.inform == "pem": | |
| 42 | + pemtobin(args.input[0], outf) | |
| 43 | + elif args.inform == "bin": | |
| 44 | + bintopem(args.input[0], outf) | |
| 45 | + else: | |
| 46 | + raise Exception("Unknown format %s" % args.inform) | |
| 47 | + | |
| 48 | +if __name__ == '__main__': | |
| 49 | + main() | ... | ... |