1*84e33947SAndroid Build Coastguard Worker#!/usr/bin/python 2*84e33947SAndroid Build Coastguard Worker 3*84e33947SAndroid Build Coastguard Worker# 4*84e33947SAndroid Build Coastguard Worker# Copyright 2024, The Android Open Source Project 5*84e33947SAndroid Build Coastguard Worker# 6*84e33947SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 7*84e33947SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 8*84e33947SAndroid Build Coastguard Worker# You may obtain a copy of the License at 9*84e33947SAndroid Build Coastguard Worker# 10*84e33947SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 11*84e33947SAndroid Build Coastguard Worker# 12*84e33947SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 13*84e33947SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 14*84e33947SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*84e33947SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 16*84e33947SAndroid Build Coastguard Worker# limitations under the License. 17*84e33947SAndroid Build Coastguard Worker# 18*84e33947SAndroid Build Coastguard Worker 19*84e33947SAndroid Build Coastguard Worker"""A script to sign nanoapps for testing purpose on tinysys platforms.""" 20*84e33947SAndroid Build Coastguard Worker 21*84e33947SAndroid Build Coastguard Workerimport argparse 22*84e33947SAndroid Build Coastguard Workerimport ctypes 23*84e33947SAndroid Build Coastguard Workerimport hashlib 24*84e33947SAndroid Build Coastguard Workerfrom cryptography.hazmat.primitives import hashes 25*84e33947SAndroid Build Coastguard Workerfrom cryptography.hazmat.primitives import serialization 26*84e33947SAndroid Build Coastguard Workerfrom cryptography.hazmat.primitives.asymmetric import ec 27*84e33947SAndroid Build Coastguard Workerfrom cryptography.hazmat.primitives.asymmetric import utils 28*84e33947SAndroid Build Coastguard Worker 29*84e33947SAndroid Build Coastguard Worker 30*84e33947SAndroid Build Coastguard Workerclass HeaderInfo(ctypes.LittleEndianStructure): 31*84e33947SAndroid Build Coastguard Worker _fields_ = [ 32*84e33947SAndroid Build Coastguard Worker ("magic_number", ctypes.c_uint32), 33*84e33947SAndroid Build Coastguard Worker ("header_version", ctypes.c_uint32), 34*84e33947SAndroid Build Coastguard Worker ("rollback_info", ctypes.c_uint32), 35*84e33947SAndroid Build Coastguard Worker ("binary_length", ctypes.c_uint32), 36*84e33947SAndroid Build Coastguard Worker ("flags", ctypes.c_uint64 * 2), 37*84e33947SAndroid Build Coastguard Worker ("binary_sha256", ctypes.c_uint8 * 32), 38*84e33947SAndroid Build Coastguard Worker ("reserved_chip_id", ctypes.c_uint8 * 32), 39*84e33947SAndroid Build Coastguard Worker ("reserved_auth_config", ctypes.c_uint8 * 256), 40*84e33947SAndroid Build Coastguard Worker ("reserved_image_config", ctypes.c_uint8 * 256), 41*84e33947SAndroid Build Coastguard Worker ] 42*84e33947SAndroid Build Coastguard Worker 43*84e33947SAndroid Build Coastguard Worker 44*84e33947SAndroid Build Coastguard Workerdef read_private_key(key_file, password): 45*84e33947SAndroid Build Coastguard Worker with open(key_file, "rb") as file: 46*84e33947SAndroid Build Coastguard Worker key_bytes = file.read() 47*84e33947SAndroid Build Coastguard Worker try: 48*84e33947SAndroid Build Coastguard Worker return serialization.load_der_private_key(key_bytes, password=password) 49*84e33947SAndroid Build Coastguard Worker except ValueError as e: 50*84e33947SAndroid Build Coastguard Worker pass # Not a DER private key 51*84e33947SAndroid Build Coastguard Worker 52*84e33947SAndroid Build Coastguard Worker try: 53*84e33947SAndroid Build Coastguard Worker return serialization.load_pem_private_key(key_bytes, password=password) 54*84e33947SAndroid Build Coastguard Worker except ValueError: 55*84e33947SAndroid Build Coastguard Worker pass # Not a PEM private key 56*84e33947SAndroid Build Coastguard Worker raise ValueError("Unable to parse the key file as DER or PEM") 57*84e33947SAndroid Build Coastguard Worker 58*84e33947SAndroid Build Coastguard Worker 59*84e33947SAndroid Build Coastguard Workerdef main(): 60*84e33947SAndroid Build Coastguard Worker 61*84e33947SAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 62*84e33947SAndroid Build Coastguard Worker description="Sign a binary to be authenticated on tinysys platforms" 63*84e33947SAndroid Build Coastguard Worker ) 64*84e33947SAndroid Build Coastguard Worker parser.add_argument( 65*84e33947SAndroid Build Coastguard Worker "private_key_file", 66*84e33947SAndroid Build Coastguard Worker help="The private key (DER or PEM format) used to sign the binary", 67*84e33947SAndroid Build Coastguard Worker ) 68*84e33947SAndroid Build Coastguard Worker parser.add_argument( 69*84e33947SAndroid Build Coastguard Worker "-p", 70*84e33947SAndroid Build Coastguard Worker "--password", 71*84e33947SAndroid Build Coastguard Worker type=str, 72*84e33947SAndroid Build Coastguard Worker help="Optional password encrypting the private key", 73*84e33947SAndroid Build Coastguard Worker ) 74*84e33947SAndroid Build Coastguard Worker parser.add_argument( 75*84e33947SAndroid Build Coastguard Worker "nanoapp", help="The name of the nanoapp binary file to be signed" 76*84e33947SAndroid Build Coastguard Worker ) 77*84e33947SAndroid Build Coastguard Worker parser.add_argument( 78*84e33947SAndroid Build Coastguard Worker "output_path", help="The path where the signed binary should be stored" 79*84e33947SAndroid Build Coastguard Worker ) 80*84e33947SAndroid Build Coastguard Worker args = parser.parse_args() 81*84e33947SAndroid Build Coastguard Worker 82*84e33947SAndroid Build Coastguard Worker # Load the binary file. 83*84e33947SAndroid Build Coastguard Worker binary_data = None 84*84e33947SAndroid Build Coastguard Worker with open(args.nanoapp, "rb") as binary_file: 85*84e33947SAndroid Build Coastguard Worker binary_data = binary_file.read() 86*84e33947SAndroid Build Coastguard Worker 87*84e33947SAndroid Build Coastguard Worker # Load ECDSA private key. 88*84e33947SAndroid Build Coastguard Worker password = args.password.encode() if args.password else None 89*84e33947SAndroid Build Coastguard Worker private_key = read_private_key(args.private_key_file, password) 90*84e33947SAndroid Build Coastguard Worker 91*84e33947SAndroid Build Coastguard Worker # Generate a zero-filled header. 92*84e33947SAndroid Build Coastguard Worker header = bytearray(0x1000) 93*84e33947SAndroid Build Coastguard Worker 94*84e33947SAndroid Build Coastguard Worker # Fill the public key. 95*84e33947SAndroid Build Coastguard Worker public_key_numbers = private_key.public_key().public_numbers() 96*84e33947SAndroid Build Coastguard Worker header[0x200:0x220] = public_key_numbers.x.to_bytes(32, "big") 97*84e33947SAndroid Build Coastguard Worker header[0x220:0x240] = public_key_numbers.y.to_bytes(32, "big") 98*84e33947SAndroid Build Coastguard Worker 99*84e33947SAndroid Build Coastguard Worker # Fill header_info. 100*84e33947SAndroid Build Coastguard Worker sha256_hasher = hashlib.sha256() 101*84e33947SAndroid Build Coastguard Worker sha256_hasher.update(binary_data) 102*84e33947SAndroid Build Coastguard Worker header_info = HeaderInfo( 103*84e33947SAndroid Build Coastguard Worker magic_number=0x45524843, 104*84e33947SAndroid Build Coastguard Worker header_version=1, 105*84e33947SAndroid Build Coastguard Worker binary_length=len(binary_data), 106*84e33947SAndroid Build Coastguard Worker binary_sha256=(ctypes.c_uint8 * 32)(*sha256_hasher.digest()), 107*84e33947SAndroid Build Coastguard Worker ) 108*84e33947SAndroid Build Coastguard Worker header_info_bytes = bytes(header_info) 109*84e33947SAndroid Build Coastguard Worker header[0x400 : 0x400 + len(header_info_bytes)] = header_info_bytes 110*84e33947SAndroid Build Coastguard Worker 111*84e33947SAndroid Build Coastguard Worker # Generate the signature. 112*84e33947SAndroid Build Coastguard Worker signature = private_key.sign(header[0x200:], ec.ECDSA(hashes.SHA256())) 113*84e33947SAndroid Build Coastguard Worker r, s = utils.decode_dss_signature(signature) 114*84e33947SAndroid Build Coastguard Worker r_bytes = r.to_bytes(32, "big") 115*84e33947SAndroid Build Coastguard Worker s_bytes = s.to_bytes(32, "big") 116*84e33947SAndroid Build Coastguard Worker header[:32] = r_bytes 117*84e33947SAndroid Build Coastguard Worker header[32:64] = s_bytes 118*84e33947SAndroid Build Coastguard Worker 119*84e33947SAndroid Build Coastguard Worker with open(f"{args.output_path}/{args.nanoapp}", "wb") as output: 120*84e33947SAndroid Build Coastguard Worker output.write(header) 121*84e33947SAndroid Build Coastguard Worker output.write(binary_data) 122*84e33947SAndroid Build Coastguard Worker 123*84e33947SAndroid Build Coastguard Worker 124*84e33947SAndroid Build Coastguard Workerif __name__ == "__main__": 125*84e33947SAndroid Build Coastguard Worker main() 126