#!/usr/bin/env python3
'''
add a set of up to 10 public keys to an ArduPilot bootloader bin file
'''

import sys
import os
import base64

try:
    import monocypher
except ImportError:
    print("Please install monocypher with: python3 -m pip install pymonocypher")
    sys.exit(1)

# get command line arguments
from argparse import ArgumentParser
parser = ArgumentParser(description='make_secure_bl')
parser.add_argument("--omit-ardupilot-keys", action='store_true', default=False, help="omit ArduPilot signing keys")
parser.add_argument("bootloader", type=str, default=None, help="bootloader")
parser.add_argument("keys", nargs='*', type=str, default=[], help="keys")
args = parser.parse_args()
    
descriptor = b'\x4e\xcf\x4e\xa5\xa6\xb6\xf7\x29'
max_keys = 10
key_len = 32

img = open(args.bootloader, 'rb').read()

offset = img.find(descriptor)
if offset == -1:
    print("Failed to find descriptor")
    sys.exit(1)

offset += 8
desc = b''
desc_len = 0

keys = []

if not args.omit_ardupilot_keys:
    print("Adding ArduPilot keys")
    signing_dir = os.path.dirname(os.path.realpath(__file__))
    keydir = os.path.join(signing_dir,"ArduPilotKeys")
    for root, dirs, files in os.walk(keydir):
        for f in files:
            if f.endswith(".dat"):
                keys.append(os.path.relpath(os.path.join(keydir, f)))

keys += args.keys[:]

if len(keys) > max_keys:
    print("Too many key files %u, max is %u" % (len(keys), max_keys))
    sys.exit(1)

if len(keys) <= 0:
    print("At least one key file required")
    sys.exit(1)

def decode_key(ktype, key):
    ktype += "_KEYV1:"
    if not key.startswith(ktype):
        print("Invalid key type")
        sys.exit(1)
    return base64.b64decode(key[len(ktype):])

for kfile in keys:
    key = decode_key("PUBLIC", open(kfile, "r").read())
    print("Applying Public Key %s" % kfile)
    if len(key) != key_len:
        print("Bad key length %u in %s" % (len(key), kfile))
        sys.exit(1)
    desc += key
    desc_len += key_len
img = img[:offset] + desc + img[offset+desc_len:]
open(sys.argv[1], 'wb').write(img)
