1#! /usr/bin/env python3 2# 3# ----------------------------------------------------------------------------- 4# Copyright (c) 2020-2024, Arm Limited. All rights reserved. 5# 6# SPDX-License-Identifier: BSD-3-Clause 7# 8# ----------------------------------------------------------------------------- 9 10import os 11import sys 12import click 13from jinja2 import Environment, FileSystemLoader 14from cryptography.hazmat.primitives.hashes import Hash, SHA256 15 16# Add the cwd to the path so that if there is a version of imgtool in there then 17# it gets used over the system imgtool. Used so that imgtool from upstream 18# mcuboot is preferred over system imgtool 19cwd = os.getcwd() 20sys.path = [cwd] + sys.path 21import imgtool 22import imgtool.main 23 24parser_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../')) 25sys.path.append(parser_path) 26 27# This works around Python 2 and Python 3 handling character encodings 28# differently. More information about this issue at 29# https://click.palletsprojects.com/en/5.x/python3 30os.environ['LC_ALL'] = 'C.UTF-8' 31os.environ['LANG'] = 'C.UTF-8' 32 33 34def get_key_hash_c_array(key_file, mcuboot_hw_key): 35 key = imgtool.main.load_key(key_file) 36 key_bytes = [] 37 if mcuboot_hw_key == "ON": 38 digest = Hash(SHA256()) 39 digest.update(key.get_public_bytes()) 40 key_bytes = digest.finalize() 41 else: 42 # If the full key is used then use only the raw key 43 # bit string (subjectPublicKey). The offset of the 44 # bit string is 26, so drop the first 26 bytes. 45 key_bytes = key.get_public_bytes()[26:] 46 47 return hex_to_c_array(key_bytes) 48 49 50@click.argument('outfile') 51@click.option('--bl2_rot_priv_key_0', metavar='filename', required=True) 52@click.option('--bl2_rot_priv_key_1', metavar='filename', required=False) 53@click.option('--bl2_rot_priv_key_2', metavar='filename', required=False) 54@click.option('--bl2_rot_priv_key_3', metavar='filename', required=False) 55@click.option('--bl2_mcuboot_hw_key', metavar='string', required=True) 56@click.option('--template_path', metavar='filename', required=True) 57@click.option('--secure_debug_pk', metavar='key', required=False) 58@click.option('--huk', metavar='key', required=False) 59@click.option('--iak', metavar='key', required=False) 60@click.option('--boot_seed', metavar='seed', required=False) 61@click.option('--implementation_id', metavar='id', required=False) 62@click.option('--certification_reference', metavar='reference', default="", 63 required=False) 64@click.option('--verification_service_url', metavar='url', default="", 65 required=False) 66@click.option('--entropy_seed', metavar='seed', required=False) 67@click.command(help='''Creates a .c file with the given keys, using the\n 68 provisioning_data_template.jinja2 template which is located in 69 "template_path" and outputs it to "outfile"''') 70def generate_provisioning_data_c(outfile, bl2_rot_priv_key_0, 71 bl2_rot_priv_key_1, bl2_mcuboot_hw_key, 72 template_path, bl2_rot_priv_key_2, 73 bl2_rot_priv_key_3, 74 secure_debug_pk, huk, iak, boot_seed, 75 implementation_id, 76 certification_reference, 77 verification_service_url, 78 entropy_seed): 79 80 environment = Environment(loader=FileSystemLoader(template_path)) 81 template = environment.get_template("provisioning_data_template.jinja2") 82 83 bl2_rot_pub_key_0_hash = "" 84 if bool(bl2_rot_priv_key_0) is True: 85 bl2_rot_pub_key_0_hash = get_key_hash_c_array( 86 bl2_rot_priv_key_0, bl2_mcuboot_hw_key) 87 88 bl2_rot_pub_key_1_hash = "" 89 if bool(bl2_rot_priv_key_1) is True: 90 bl2_rot_pub_key_1_hash = get_key_hash_c_array( 91 bl2_rot_priv_key_1, bl2_mcuboot_hw_key) 92 93 bl2_rot_pub_key_2_hash = "" 94 if bool(bl2_rot_priv_key_2) is True: 95 bl2_rot_pub_key_2_hash = get_key_hash_c_array( 96 bl2_rot_priv_key_2, bl2_mcuboot_hw_key) 97 98 bl2_rot_pub_key_3_hash = "" 99 if bool(bl2_rot_priv_key_3) is True: 100 bl2_rot_pub_key_3_hash = get_key_hash_c_array( 101 bl2_rot_priv_key_3, bl2_mcuboot_hw_key) 102 103 if bool(huk) is False: 104 huk = hex_to_c_array(os.urandom(32)) 105 106 if bool(iak) is False: 107 iak = hex_to_c_array(os.urandom(32)) 108 109 if bool(boot_seed) is False: 110 boot_seed = hex_to_c_array(os.urandom(32)) 111 112 if bool(implementation_id) is False: 113 implementation_id = hex_to_c_array(os.urandom(32)) 114 115 if bool(entropy_seed) is False: 116 entropy_seed = hex_to_c_array(os.urandom(64)) 117 118 key_arrays = { 119 "bl2_rotpk_0": bl2_rot_pub_key_0_hash, 120 "bl2_rotpk_1": bl2_rot_pub_key_1_hash, 121 "bl2_rotpk_2": bl2_rot_pub_key_2_hash, 122 "bl2_rotpk_3": bl2_rot_pub_key_3_hash, 123 "secure_debug_pk": secure_debug_pk, 124 "huk": huk, 125 "iak": iak, 126 "iak_len": "32", 127 "boot_seed": boot_seed, 128 "implementation_id": implementation_id, 129 "certification_reference": certification_reference, 130 "verification_service_url": verification_service_url, 131 "entropy_seed": entropy_seed 132 } 133 134 with open(outfile, "w") as F: 135 F.write(template.render(key_arrays)) 136 137 138def hex_to_c_array(hex_val): 139 c_array = "" 140 for count, b in enumerate(hex_val): 141 if count % 8 == 0 and count != 0: 142 c_array = c_array + '\n' 143 c_array = c_array + "0x{:02x}, ".format(b) 144 145 return c_array 146 147 148if __name__ == '__main__': 149 generate_provisioning_data_c() 150