# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2020-2021 Damien P. George # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ Utility to create compressed, encrypted and signed DFU files. """ import argparse import os import re import struct import sys import zlib sys.path.append(os.path.dirname(__file__) + "/../../../tools") import dfu try: import pyhy except ImportError: raise SystemExit( "ERROR: pyhy not found. Please install python pyhy for encrypted mboot support: pip3 install pyhy" ) # Currenty supported version of a packed DFU file. MBOOT_PACK_HEADER_VERSION = 1 # Must match MBOOT_PACK_HYDRO_CONTEXT in mboot/pack.h MBOOT_PACK_HYDRO_CONTEXT = "mbootenc" # Must match enum in mboot/pack.h. MBOOT_PACK_CHUNK_META = 0 MBOOT_PACK_CHUNK_FULL_SIG = 1 MBOOT_PACK_CHUNK_FW_RAW = 2 MBOOT_PACK_CHUNK_FW_GZIP = 3 class Keys: def __init__(self, filename): self.filename = filename def generate(self): kp = pyhy.hydro_sign_keygen() self.sign_sk = kp.sk self.sign_pk = kp.pk self.secretbox = pyhy.hydro_secretbox_keygen() def _save_data(self, name, data, file_, hide=False): prefix = "//" if hide else "" data = ",".join("0x{:02x}".format(b) for b in data) file_.write("{}const uint8_t {}[] = {{{}}};\n".format(prefix, name, data)) def _load_data(self, name, line): line = line.split(name + "[] = ") if len(line) != 2: raise Exception("malformed input keys: {}".format(line)) data = line[1].strip() return bytes(int(value, 16) for value in data[1:-2].split(",")) def save(self): with open(self.filename, "w") as f: self._save_data("mboot_pack_sign_secret_key", self.sign_sk, f, hide=True) self._save_data("mboot_pack_sign_public_key", self.sign_pk, f) self._save_data("mboot_pack_secretbox_key", self.secretbox, f) def load(self): with open(self.filename) as f: for line in f: for key, attr in ( ("mboot_pack_sign_secret_key", "sign_sk"), ("mboot_pack_sign_public_key", "sign_pk"), ("mboot_pack_secretbox_key", "secretbox"), ): if key in line: setattr(self, attr, self._load_data(key, line)) def dfu_read(filename): elems = [] with open(filename, "rb") as f: hdr = f.read(11) sig, ver, size, num_targ = struct.unpack("<5sBIB", hdr) file_offset = 11 for i in range(num_targ): hdr = f.read(274) sig, alt, has_name, name, t_size, num_elem = struct.unpack("<6sBi255sII", hdr) file_offset += 274 file_offset_t = file_offset for j in range(num_elem): hdr = f.read(8) addr, e_size = struct.unpack("