def __init__(self, dev_type, dev_rev, app_ver, sd_ver, key_file, image_file): self.DeviceType = dev_type self.DeviceRevision = dev_rev self.ApplicationVersion = app_ver self.SoftDeviceVersions = sd_ver self.HMAC = "" self.init_pkt = "" # Generate bin file bin_file = StringIO.StringIO() hex2bin(image_file, bin_file) fkey = open(key_file, "r") self.key = fkey.read().strip() self.msg = bin_file.getvalue() if len(self.key) < 32: print "ERROR: Expected key length 32, but got key length " + str(len(self.key)) exit(1) self.HMAC = self.GenerateHMAC(self.key, self.msg, image_file.replace("hex","bin")) self.init_pkt += self.GenerateInitPkt() self.init_pkt += self.HMAC fkey.close()
def uploadHex (self, file): buffer = BytesIO () intelhex.hex2bin (file, buffer) bin = buffer.getvalue () self.uploadFlash (0, bin) if self.downloadFlash (0, len (bin)) != bin: raise IOError (_('Verification failed'))
def program_device(firmware_path, port): filename, file_extension = os.path.splitext(firmware_path) if file_extension == '.hex': hex2bin(firmware_path, filename + '.binary') firmware_path = filename + '.binary' ser = serial.Serial(port=port, baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=0.1) ser.write(b"system bootloader\r\n") ser.close() time.sleep(0.1) loader = Stm32Loader() loader.configuration['data_file'] = firmware_path loader.configuration['port'] = port loader.configuration['erase'] = True loader.configuration['write'] = True loader.configuration['verify'] = True loader.configuration['go_address'] = 0x08000000 loader.configuration['baud'] = 115200 loader.connect() loader.read_device_details() time.sleep(0.1) loader.perform_commands() loader.reset()
def hex_to_bin(): # hex文件转成bin文件 hex_file_name, bin_file_name = get_hex_file_name() hex_file_path = os.path.join(file_path, hex_file_name) bin_file_path = os.path.join(file_path, bin_file_name) hex2bin(hex_file_path, bin_file_path, start, end, size, pad) return bin_file_path
def __init__(self, dev_type, dev_rev, app_ver, sd_ver, key_file, image_file): self.DeviceType = dev_type self.DeviceRevision = dev_rev self.ApplicationVersion = app_ver self.SoftDeviceVersions = sd_ver self.HMAC = "" self.init_pkt = "" # Generate bin file bin_file = StringIO.StringIO() hex2bin(image_file, bin_file) fkey = open(key_file, "r") self.key = fkey.read().strip() self.msg = bin_file.getvalue() if len(self.key) < 32: print "ERROR: Expected key length 32, but got key length " + str( len(self.key)) exit(1) self.HMAC = self.GenerateHMAC(self.key, self.msg, image_file.replace("hex", "bin")) self.init_pkt += self.GenerateInitPkt() self.init_pkt += self.HMAC fkey.close()
def upload_hex (self, file): print ('Uploading firmware...') buffer = BytesIO () intelhex.hex2bin (file, buffer) bin = buffer.getvalue () self.upload_flash (0, bin) print ('Verifying...') if self.download_flash (0, len (bin)) != bin: raise IOError ('Verification failed') print ('Done.')
def upload_hex(self, file): print('Uploading firmware...') buffer = BytesIO() intelhex.hex2bin(file, buffer) bin = buffer.getvalue() self.upload_flash(0, bin) print('Verifying...') if self.download_flash(0, len(bin)) != bin: raise IOError('Verification failed') print('Done.')
def sign_image(self, hex_file, image_id): """ Signs hex file with the key specified in the policy file. Converts binary file of the signed image. Creates copy of unsigned hex file. Encrypts UPGRADE image if the policy file contains encryption key :param hex_file: The hex file to sign. :param image_id: The ID of the firmware in policy file. :return: Path to the signed files. One file per slot. """ result = [] slot = self.parser.get_slot(image_id) for image in slot['resources']: # Sign BOOT image and encrypt+sign UPGRADE image if 'encrypt' in slot and slot['encrypt'] and image[ 'type'] == ImageType.UPGRADE.name: hex_out = self.encrypt_image(slot, image['type'], unsigned_boot_hex) else: if image['type'] == ImageType.UPGRADE.name: if 'upgrade' not in slot or not slot['upgrade']: continue # skip generating hex file for UPGRADE slot if it is disabled # Preserve hex file for cm4 image if slot['id'] == self.memory_map.NSPE_IMAGE_ID: out_cm4_hex = '{0}_{2}{1}'.format( *os.path.splitext(hex_file) + ('cm4', )) copy2(hex_file, out_cm4_hex) # Sign image if image['type'] == ImageType.BOOT.name: unsigned_boot_hex = '{0}_{2}{1}'.format( *os.path.splitext(hex_file) + ('unsigned', )) copy2(hex_file, unsigned_boot_hex) hex_out = self.sign_single_hex(slot, image['type'], hex_file, hex_file) # Produce hex file for slot1 if image['type'] == ImageType.UPGRADE.name: output_name = '{0}_{2}{1}'.format( *os.path.splitext(hex_file) + ('upgrade', )) hex_out = self.sign_single_hex(slot, image['type'], unsigned_boot_hex, output_name) bin_out = '{0}.bin'.format(os.path.splitext(hex_out)[0]) hex2bin(hex_out, bin_out) bin2hex(bin_out, output_name, offset=int(image['address'])) os.remove(bin_out) logger.info(f'Image UPGRADE: {hex_out}\n') # Replace input hex file with the result.append(hex_out) os.remove(unsigned_boot_hex) result = tuple(result) if len(result) > 0 else None return result
def test_binary_verify(self, device): """Creates a binary image from the hex image and tries to flash the device. Checks two test cases: 1) fails when trying to verify binary image with 'bin' bool set to False; 2) passes when trying to verify binary image with 'bin' bool set to True; """ # Ensure image is a hex file assert device['image'].endswith(".hex") hex_path = device['image'] bin_path = hex_path[:-3] + "bin" # Convert .hex image to .bin intelhex.hex2bin(hex_path, bin_path) # Basic Binary Test result = tiflash.flash(bin_path, binary=True, serno=device['serno'], connection=device['connection'], devicetype=device['devicetype']) if result is False: pytest.skip("Flashing of image needs to work in order for this" "test to run") result = tiflash.verify(bin_path, binary=True, serno=device['serno'], connection=device['connection'], devicetype=device['devicetype']) assert result is True # Verifying binary without specifying binary=True with pytest.raises(tiflash.TIFlashError): result = tiflash.verify(bin_path, binary=True, serno=device['serno'], connection=device['connection'], devicetype=device['devicetype']) # Verifying hex image with specifying binary image = True with pytest.raises(tiflash.TIFlashError): result = tiflash.verify(hex_path, binary=True, serno=device['serno'], connection=device['connection'], devicetype=device['devicetype'])
def test_binary_verify(self, device): """Creates a binary image from the hex image and tries to flash the device. Checks two test cases: 1) fails when trying to flash binary image with 'bin' bool set to False; 2) passes when trying to flash binary image with 'bin' bool set to True; """ # Ensure image is a hex file assert device['image'].endswith(".hex") hex_path = device['image'] bin_path = hex_path[:-3] + "bin" # Convert .hex image to .bin intelhex.hex2bin(hex_path, bin_path) # Basic Binary Flash cmd = get_cmd_with_device_params(device) cmd.extend(["flash", "\"%s\"" % bin_path, "--bin"]) cmd_str = " ".join(cmd) subprocess.check_call(cmd_str, shell=True) # Basic Binary Verify cmd = get_cmd_with_device_params(device) cmd.extend(["verify", "\"%s\"" % bin_path, "--bin"]) cmd_str = " ".join(cmd) subprocess.check_call(cmd_str, shell=True) # Verifying binary without specifying binary=True cmd = get_cmd_with_device_params(device) cmd.extend(["verify", "\"%s\"" % bin_path]) cmd_str = " ".join(cmd) subprocess.check_call(cmd_str, shell=True) # Verify hex image with specifying binary image = True with pytest.raises(subprocess.CalledProcessError): cmd = get_cmd_with_device_params(device) cmd.extend(["verify", "\"%s\"" % hex_path, "--bin"]) cmd_str = " ".join(cmd) subprocess.check_call(cmd_str, shell=True)
def getStackImgRange(projdir, stackHexFileName, boundary_address, outputPath): stack_boundary, flash_limit = getStackRange(boundary_address) # Generate binary file if stackHexFileName.endswith('.hex'): outfileStackPath = os.path.abspath(stackHexFileName[:-4] + ".bin") else: raise Exception("Stack hex not valid") intelhex.hex2bin(stackHexFileName, outfileStackPath, start=stack_boundary, end=flash_limit) # Get the image range imgRange = imgBinUtil.getImgRange([outfileStackPath, imgStartOffset, imgEndOffset, imgLenOffset]) return imgRange
def createTgtBinfile(projType, projdir, binaryFileType, appHexFileName, tgtBdFileName, outputPath): # Find boundary if projType == 'ccs': boundary_address = getBoundary_CCS(projdir) else: boundary_address = getTgtBoundary(tgtBdFileName) stack_boundary, flash_limit = getStackRange(boundary_address) flash_path = os.path.join(projdir, appHexFileName) outfileTargetPath = os.path.abspath(outputPath + ".bin") intelhex.hex2bin(flash_path, outfileTargetPath, start=stack_boundary, end=flash_limit) imgBinUtil.updateImageLen([outfileTargetPath, imgStartOffset, imgEndOffset, imgLenOffset]) computeCRC32.computeCRC32([outfileTargetPath, '12', '8'])
def send_file(self): """ Отправка файла в COM порт. """ try: #Проверка на скорость передачи self.boud = self.listWidget_2.currentItem().text() except: buttonReply = QtWidgets.QMessageBox.warning( self, 'Ошибка', "Выберите скорость предачи.", QtWidgets.QMessageBox.Ok) try: #Проверка на выбранный порт self.com_port = self.listWidget.currentItem().text() except: buttonReply = QtWidgets.QMessageBox.warning( self, 'Ошибка', "Выберите COM порт.", QtWidgets.QMessageBox.Ok) if not self.path_file: #Проверка на выбранный файл buttonReply = QtWidgets.QMessageBox.warning( self, 'Ошибка', "Выберите файл для прошивки.", QtWidgets.QMessageBox.Ok) else: if self.path_file.endswith('.hex'): #Если файл hex in_file = self.path_file out_file = '{0}.bin'.format(self.path_file.split('.')[0]) hex2bin(in_file, out_file) #Конвертирование else: out_file = self.path_file ser = serial.Serial() #Создаем экземпляр подключения к порту ser.baudrate = int(self.boud) #Задаем скорость передачи ser.port = self.com_port #Задаем порт для подключения if not ser.is_open: ser.open() # Если не открыт порт, то открываем. with open(out_file, "rb") as f: byte = f.read(16) while byte != b'': # Окончание бинарного файла byte = f.read(16) ser.write(byte) ser.close() #Закрываем порт buttonReply = QtWidgets.QMessageBox.question( self, 'Успешно', "Отправка данных успешно завершена", QtWidgets.QMessageBox.Ok) #Выводим сообщение об отправке
def convert_file_format(filename, firmware_version='0100', firmware_type='APP', module_number='', start=None, end=None, size=None): """convert hexadecimal format to binary format""" (fname, ext) = os.path.splitext(filename) bin_file = fname + "_" + firmware_type + ".bin" with open(filename, 'rb' if ext == '.bin' else 'rt') as fin, open(bin_file, 'wb') as fout: if firmware_type.upper().startswith('DSP'): if ext == '.txt': convert_dsp_file_format(fin, fout) elif ext == '.bin': convert_binary_dsp_file(fin, fout) else: hex2bin(fin, fout, start, end, size, pad=0xFF) append_vendor_info(bin_file, firmware_version, firmware_type, start, module_number)
if len(args) > 2: raise getopt.GetoptError('Too many arguments') except getopt.GetoptError, msg: txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool print(txt) print(usage) sys.exit(2) fin = args[0] if not os.path.isfile(fin): txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool print(txt) sys.exit(1) if len(args) == 2: fout = args[1] else: # write to stdout fout = sys.stdout # force binary mode for stdout on Windows if os.name == 'nt': f_fileno = getattr(sys.stdout, 'fileno', None) if f_fileno: fileno = f_fileno() if fileno >= 0: import msvcrt msvcrt.setmode(fileno, os.O_BINARY) sys.exit(hex2bin(fin, fout, start, end, size, pad))
import intelhex import sys import os import struct """ Convert intel hex output from Atmel Studio to binary payloads for ROP.py """ args = sys.argv[1:] if len(args) == 2: fin = args[0] fout = args[1] intelhex.hex2bin(fin, fout, None, None, None, None) res = '' with open(fout, 'r') as f: first = f.read(1) second = f.read(1) while second != '': res += second + first first = f.read(1) second = f.read(1) with open(fout, 'w') as fw: fw.write(res)
def createAppStackBinfile(projType, projdir, binaryFileType, appHexFileName, bdFileName, outputPath, stackHexFileName=None): # Find boundary, if there is one if (bdFileName is not None): if projType == 'ccs': boundary_address = getBoundary_CCS(bdFileName) else: boundary_address = getBoundary(bdFileName) if (binaryFileType == 3 or binaryFileType == 7): #Merged App + Stack or app + stack library app_path = os.path.join(projdir, appHexFileName) outfileAppPath = os.path.join(projdir, outputPath) outfileAppPath = os.path.abspath(outfileAppPath + ".bin") # Generate application binary intelhex.hex2bin(app_path, outfileAppPath) # Get the image range if (binaryFileType == 7): imgStartOffset = 52 #0x34 imgRngParams = [ outfileAppPath, imgStartOffset, imgEndOffset, imgLenOffset ] imgStAddr, imgEndAddr = imgBinUtil.getImgRange(imgRngParams) #pad end if it is not word aligned imgLen = imgEndAddr - imgStAddr + 1 if (imgLen & 3): imgEndAddr = imgEndAddr - (imgLen & 3) + 4 # Run the hex2bin to get correct length binary image intelhex.hex2bin(app_path, outfileAppPath, start=imgStAddr, end=imgEndAddr) # Update imageLength field imgBinUtil.updateImageLen( [outfileAppPath, imgStartOffset, imgEndOffset, imgLenOffset]) if (binaryFileType == 3): # Update image segment's length field imgBinUtil.updateImageSegLen([ outfileAppPath, imgStartOffset, imgEndOffset, (fixedHdrLen + boundrySegLen + 4), fixedHdrLen + boundrySegLen ]) # Update file type field imgBinUtil.fileTypeTag([outfileAppPath, "3", "18"]) else: # Update image segment's length field imgBinUtil.updateImageSegLen([ outfileAppPath, imgStartOffset, imgEndOffset, (fixedHdrLen + 4), fixedHdrLen ]) # Update file type field imgBinUtil.fileTypeTag([outfileAppPath, "7", "18"]) # Update crc32 field computeCRC32.computeCRC32([outfileAppPath, "12", "8"]) elif (binaryFileType == 2): # Stack only stack_boundary, flash_limit = getStackRange(boundary_address) stack_path = os.path.join(projdir, appHexFileName) outfileStackPath = os.path.abspath(stack_path + ".bin") # Generate binary file outfileStackPath = os.path.join(projdir, outputPath) outfileStackPath = outfileStackPath + ".bin" intelhex.hex2bin(stack_path, outfileStackPath, start=stack_boundary, end=flash_limit) # Get the image range args = [outfileStackPath, imgStartOffset, imgEndOffset, imgLenOffset] imgStAddr, imgEndAddr = imgBinUtil.getImgRange(args) #pad end if it is not word aligned imgLen = imgEndAddr - imgStAddr + 1 if (imgLen & 3): imgEndAddr = imgEndAddr - (imgLen & 3) + 4 # Rerun hex2bin to get correct length of binary image intelhex.hex2bin(stack_path, outfileStackPath, start=imgStAddr, end=imgEndAddr) imgBinUtil.updateImageLen( [outfileStackPath, imgStartOffset, imgEndOffset, imgLenOffset]) imgBinUtil.updateImageSegLen([ outfileStackPath, imgStartOffset, imgEndOffset, payloadSegLenOffset, fixedHdrLen + boundrySegLen ]) computeCRC32.computeCRC32([outfileStackPath, "12", "8"]) elif (binaryFileType == 1): # Get app image range appImgStartAddr, app_boundary = getAppRange(boundary_address) # To get the actual stack range, need to build stack binary and then # read the image header to find the actual address stack_boundary, flash_limit = getStackImgRange(projdir, stackHexFileName, boundary_address, outputPath) app_path = os.path.join(projdir, appHexFileName) stack_path = os.path.join(projdir, stackHexFileName) outfileAppPath = os.path.join(projdir, outputPath) + ".bin" # Generate application binary intelhex.hex2bin(app_path, outfileAppPath, start=appImgStartAddr, end=app_boundary) # Get the image range imgRngParams = [ outfileAppPath, imgStartOffset, imgEndOffset, imgLenOffset ] imgStAddr, imgEndAddr = imgBinUtil.getImgRange(imgRngParams) #pad end if it is not word aligned imgLen = imgEndAddr - imgStAddr + 1 if (imgLen & 3): imgEndAddr = imgEndAddr - (imgLen & 3) + 4 # Rerun the hex2bin to get correct length binary image intelhex.hex2bin(app_path, outfileAppPath, start=imgStAddr, end=imgEndAddr) # Update file type field imgBinUtil.fileTypeTag([outfileAppPath, "1", "18"]) print "outfileAppPath: " + str( outfileAppPath) + "imgStartOffset: " + str( imgStartOffset) + "imgEndOffset" + str( imgEndOffset) + "imgLenOffset" + str(imgLenOffset) # Update imageLength field imgBinUtil.updateImageLen( [outfileAppPath, imgStartOffset, imgEndOffset, imgLenOffset]) # Update image segment's length field imgBinUtil.updateImageSegLen([ outfileAppPath, imgStartOffset, imgEndOffset, payloadSegLenOffset, fixedHdrLen + boundrySegLen ]) # Update crc32 field computeCRC32.computeCRC32([outfileAppPath, "12", "8"]) # Generate merged binary flashRange = str(hex(appImgStartAddr)) + ':' + str(hex(flash_limit)) mergedBinLen = getMergeBinLen(flashRange) # Create IntelHex objects for each hex appHex = intelhex.IntelHex(app_path) stackHex = intelhex.IntelHex(stack_path) # Define boundaries for each hex appHex = appHex[appImgStartAddr:app_boundary + 1] stackHex = stackHex[stack_boundary:flash_limit + 1] # Merge hex's inputHexFiles = [appHex, stackHex] mergedHex = intelhex.IntelHex() for hexFile in inputHexFiles: try: mergedHex.merge(hexFile, overlap="replace") except: print("Fatal Error: FAILED merge due to overlap when merging") sys.exit(1) # Define boundaries for merged hex mergedHex = mergedHex[appImgStartAddr:flash_limit + 1] # Write hex to file # mergeHexFilePath = os.path.abspath(outputPath + "_merged.hex") # print "mergeHexFilePath:::: " + mergeHexFilePath mergeHexFilePath = os.path.join(projdir, outputPath) + "_merged.hex" mergedHex.write_hex_file(mergeHexFilePath) # Convert hex to bin outFileMergedPath = os.path.join(projdir, outputPath) + "_merged.bin" intelhex.hex2bin(mergeHexFilePath, outFileMergedPath, start=appImgStartAddr, end=flash_limit) imgBinUtil.fileTypeTag([outFileMergedPath, "3", "18"]) # Update imageLength field imgBinUtil.updateMergedImageLen( [outFileMergedPath, mergedBinLen, imgLenOffset]) args = [ outFileMergedPath, mergedBinLen, imgEndOffset, payloadSegLenOffset ] imgBinUtil.updateMergedImageSegLen(args) mergedImgEndAddr = getMergeBinEndAddr(flashRange) imgBinUtil.updateMergedImageEndAddr( [outFileMergedPath, mergedImgEndAddr, imgEndOffset]) # Add crc32 bytes computeCRC32.computeCRC32([outFileMergedPath, "12", "8"])
def sign_image(toolchain, binf): """ Adds signature to a binary file being built, prepares some intermediate binary artifacts. :param toolchain: Toolchain object of current build session :param binf: Binary file created for target """ from pathlib import PurePath target_sig_data = None # reserve name for separate NSPE image out_cm4_hex = binf[:-4] + "_cm4.hex" # preserve original hex file from mbed-os build mbed_hex = binf[:-4] + "_unsigned.hex" copy2(binf, mbed_hex) # find target name and type before processing for part in PurePath(binf).parts: if "CY" in part: target_sig_data = process_target(toolchain=toolchain, target=part) if target_sig_data is None: toolchain.notify.debug("[PSOC6.sign_image] ERROR: Target not found!") raise AddSignatureError( "PSOC6.sign_image finished execution with errors! Signature is not added." ) for slot in target_sig_data: # first check if image for slot under processing should be encrypted if slot["slot_data"].get("encrypt") is True: # call encrypt_img to perform encryption args = [ sys.executable, str(slot["sdk_path"] / "encrypted_image_runner.py"), "--sdk-path", str(slot["sdk_path"]), "--hex-file", os.getcwd() + '/' + mbed_hex, "--key-priv", str(slot["sdk_path"] / slot["key_file"]), "--key-pub", str(slot["sdk_path"] / slot["dev_pub_key"]), "--key-aes", str(slot["sdk_path"] / slot["aes_key"]), "--ver", str(slot["img_data"]["VERSION"]), "--img-id", str(slot["id"]), "--rlb-count", str(slot["img_data"]["ROLLBACK_COUNTER"]), "--slot-size", str(hex(slot["slot_data"]["size"])), "--img-offset", str(slot["slot_data"]["address"]) ] if slot["slot_data"]["type"] != "BOOT": args.append("--pad") process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # catch standard process pipes outputs stderr = process.communicate()[1] stdout = process.communicate()[0] rc = process.wait() toolchain.notify.info(stdout.decode("utf-8")) if rc != 0: toolchain.notify.debug( "[PSOC6.sign_image] ERROR: Encryption script ended with error!" ) toolchain.notify.debug( "[PSOC6.sign_image] Message from encryption script: " + stderr.decode("utf-8")) raise AddSignatureError( "PSOC6.sign_image finished execution with errors! Signature is not added." ) else: toolchain.notify.info( "[PSOC6.sign_image] SUCCESS: Image for slot " + slot["slot_data"]["type"] + " is signed and encrypted with no errors!") # all non ecrypted images take this path else: if slot["slot_data"]["type"] == "UPGRADE": out_hex_name = binf[:-4] + "_upgrade.hex" else: out_hex_name = binf out_bin_name = out_hex_name[:-4] + "_signed.bin" # call imgtool for signature args = [ sys.executable, str(slot["sdk_path"] / "imgtool/imgtool.py"), "sign", "--key", str(slot["sdk_path"] / slot["key_file"]), "--header-size", str(hex(MCUBOOT_HEADER_SIZE)), "--pad-header", "--align", "8", "--version", str(slot["img_data"]["VERSION"]), "--image-id", str(slot["id"]), "--rollback_counter", str(slot["img_data"]["ROLLBACK_COUNTER"]), "--slot-size", str(hex(slot["slot_data"]["size"])), "--overwrite-only", mbed_hex, out_hex_name ] if slot["slot_data"]["type"] != "BOOT": args.append("--pad") process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # catch stderr outputs stderr = process.communicate()[1] rc = process.wait() if rc != 0: toolchain.notify.debug( "[PSOC6.sign_image] ERROR: Signature is not added!") toolchain.notify.debug( "[PSOC6.sign_image] Message from imgtool: " + stderr.decode("utf-8")) raise AddSignatureError( "PSOC6.sign_image finished execution with errors! Signature is not added." ) else: toolchain.notify.info( "[PSOC6.sign_image] SUCCESS: Image for slot " + slot["slot_data"]["type"] + " is signed with no errors!") # preserve signed binary file hex2bin(out_hex_name, out_bin_name) # preserve separate hex for cm4 # 16 is image ID for NSPE image if slot["id"] == NSPE_IMAGE_ID: copy2(out_hex_name, out_cm4_hex) # produce hex file for slot1 if slot["slot_data"]["type"] == "UPGRADE": bin2hex(out_bin_name, out_hex_name, offset=int(slot["slot_data"]["address"])) toolchain.notify.info("Image UPGRADE: " + out_hex_name + "\n")
def main(sdk_path, hex_file, key_priv, key_pub, key_aes, version, img_id, rlb_count, slot_size, pad, img_offset): """ Function consequentially performs operations with provided hex file and produces an encrypted and signed hex file for UPGRADE """ check_file_exist(key_priv) check_file_exist(key_pub) check_file_exist(key_aes) check_file_exist(hex_file) in_f = '{0}_{2}.bin'.format(*os.path.splitext(hex_file) + ('i', )) out_f = '{0}_{2}.bin'.format(*os.path.splitext(hex_file) + ('o', )) hex_file_final = get_final_hex_name(hex_file) print("Image UPGRADE:" + hex_file_final) hex2bin(hex_file, in_f) # call imgtool for signature process = subprocess.Popen([ sys.executable, os.path.join(sdk_path, "../imgtool/imgtool.py"), "sign", "--key", key_priv, "--header-size", str(hex(HEADER_SIZE)), "--pad-header", "--align", "8", "--version", version, "--image-id", img_id, "--rollback_counter", rlb_count, "--slot-size", slot_size, "--overwrite-only", in_f, out_f ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, in_f, out_f) # call aesHeader for crypto header generation process = subprocess.Popen([ sys.executable, os.path.join(sdk_path, "../imgtool/create_aesHeader.py"), "-k", key_priv, "-p", key_pub, "--key_to_encrypt", key_aes, AES_HEADER ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # catch stderr outputs process.communicate() process.wait() check_file_exist(AES_HEADER) # aes_cipher.py script file should be in the same folder as imgtool.py # encrypt signed image process = subprocess.Popen([ sys.executable, os.path.join(sdk_path, "../imgtool/aes_cipher.py"), "-k", key_aes, out_f, in_f ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, out_f, in_f) # second part - obtain signed image from encrypted file - with padding - for staging area # call imgtool for signature process = subprocess.Popen([ sys.executable, os.path.join(sdk_path, "../imgtool/imgtool.py"), "sign", "--key", key_priv, "--header-size", str(hex(HEADER_SIZE)), "--pad-header", "--align", "8", "--version", version, "--image-id", img_id, "--rollback_counter", rlb_count, "--slot-size", slot_size, "--overwrite-only", "--pad", "-a", AES_HEADER, in_f, out_f ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, in_f, out_f) bin2hex(out_f, hex_file_final, int(img_offset)) os.remove(out_f) os.remove(AES_HEADER)
def on_mergeButton_clicked(self): #error tmpFirstHex = self.firstlineEdit.text() tmpSecondHex = self.secondlineEdit.text() if (tmpFirstHex == '' or tmpSecondHex == ''): #print('error') errInput = QtGui.QMessageBox.warning(self, '提示', "请选择两个hex文件,注意顺序", QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok) if errInput == QtGui.QMessageBox.Yes: return #自定义对话框 #customMsgBox=QtGui.QMessageBox(self) #customMsgBox.setWindowTitle("提示") #customMsgBox.addButton("确定", QtGui.QMessageBox.ActionRole) #customMsgBox.addButton(self.tr("解锁"), QtGui.QMessageBox.ActionRole) #customMsgBox.addButton("cancel",QtGui.QMessageBox.ActionRole) #customMsgBox.setText("请选择两个hex文件,注意顺序!") #customMsgBox.exec_() else: #firstHex = os.path.basename(self.firstlineEdit.text()) #secondHex = os.path.basename(self.secondlineEdit.text()) curFirstPath = os.path.abspath(self.firstlineEdit.text()) curSecondPath = os.path.abspath(self.secondlineEdit.text()) #get file name #tmp_name = os.path.basename(firstHex) binfile1 = curFirstPath[0:-4] + '.bin' #tmp_name = os.path.basename(secondHex) binfile2 = curSecondPath[0:-4] + '~' + '.bin' binfile_name = curSecondPath[0:-4] + '.bin' if (os.path.isfile(binfile_name)): os.remove(binfile_name) #hex to bin self.statustextBrowser.setText("Hex to Bin and Merge Bin file....") self.statustextBrowser.append("Hex File To Bin File...") self.statustextBrowser.append("*****************************") #self.statustextBrowser.append(firstHex) #self.statustextBrowser.append(secondHex) self.statustextBrowser.append(curFirstPath) self.statustextBrowser.append(curSecondPath) self.statustextBrowser.append(binfile1) self.statustextBrowser.append(binfile2) self.statustextBrowser.append("*****************************") #self.statustextBrowser.append("") intelhex.hex2bin(curFirstPath, binfile1, None, None, None, 00) intelhex.hex2bin(curSecondPath, binfile2, None, None, None, 00) self.statustextBrowser.append("Hex File To Bin File completly") #merge two files self.statustextBrowser.append(binfile1) self.statustextBrowser.append(binfile2) bin_boot_len = os.path.getsize(binfile1) bin_app_len = os.path.getsize(binfile2) self.statustextBrowser.append("First Bin File size is %d" % (bin_boot_len)) self.statustextBrowser.append("Second Bin File size is %d" % (bin_app_len)) bin_boot_file = open(binfile1, 'rb') bin_app_file = open(binfile2, 'rb') bin_file = open(binfile_name, 'ab') for h in bin_boot_file.readlines(): #print(h) bin_file.write(h) bin_file.seek(2) bin_app_file.seek(bin_boot_len, 0) for h in bin_app_file.readlines(): #print(h) bin_file.write(h) bin_boot_file.close() bin_app_file.close() bin_file.close() bin_file_len = os.path.getsize(binfile_name) self.statustextBrowser.append("Bin File size is %d " % bin_file_len) self.statustextBrowser.append("")
def sign_image(self, hex_file, image_id, image_type, encrypt_key=None, erased_val=None, boot_record='default'): """ Signs hex file with the key specified in the policy file. Converts binary file of the signed image. Creates copy of unsigned hex file. Encrypts UPGRADE image if the policy file contains encryption key :param hex_file: The hex file to sign. :param image_id: The ID of the firmware in policy file. :param image_type: The image type. :param encrypt_key: path to public key file for the image encryption :param erased_val: The value that is read back from erased flash :param boot_record: Create CBOR encoded boot record TLV. The sw_type represents the role of the software component (e.g. CoFM for coprocessor firmware). [max. 12 characters] :return: Path to the signed files. One file per slot. """ result = [] slot = self.parser.get_slot(image_id) if erased_val: self.erased_val = erased_val ih_padding = int(erased_val, 0) logger.warning(f'Custom value {erased_val} will be used as an ' f'erased value for all regions and memory types. ' f'Typical correct values for internal and ' f'external Flash memory are 0x00 and 0xFF ' f'respectively.') else: default_erased_val = self._default_erased_value(image_type, slot) ih_padding = int(default_erased_val, 0) if slot is None: logger.error( f'Image with ID {image_id} not found in \'{self.policy_file}\'' ) return None unsigned_hex = '{0}_{2}{1}'.format(*os.path.splitext(hex_file) + ('unsigned', )) copy2(hex_file, unsigned_hex) boot_ih = IntelHex() boot_ih.padding = ih_padding boot_ih.loadfile(hex_file, 'hex') base_addr = boot_ih.minaddr() boot_bin = f'{hex_file}.bin' hex2bin(boot_ih, boot_bin) encrypted_boot = False first_image_result = None # indicates first image signing success for image in slot['resources']: if image_type: if image['type'] != image_type.upper(): continue # skip generating hex file if sign type defined and not same as current image type if image['type'] == ImageType.UPGRADE.name: if 'upgrade' not in slot or not slot['upgrade']: continue # skip generating hex file for UPGRADE slot if it is disabled encryption = self.parser.encryption_enabled(slot['id']) if encryption: if encrypt_key is None: encrypt_key = self.parser.encrypt_key(slot['id']) if encrypt_key is None: raise ValueError('Encryption key not specified') else: if not os.path.isfile(encrypt_key): raise FileNotFoundError( f'Encryption key \'{encrypt_key}\' not found') else: encrypt_key = None if image['type'] == ImageType.BOOT.name: if first_image_result is False: continue hex_out = self.sign_single_hex(slot, image['type'], boot_bin, hex_file, start_addr=base_addr, boot_record=boot_record, encrypt_key=encrypt_key) encrypted_boot = encrypt_key is not None first_image_result = hex_out is not None os.remove(boot_bin) else: if first_image_result is False: continue output_name = '{0}_{2}{1}'.format(*os.path.splitext(hex_file) + ('upgrade', )) hex_out = self.sign_single_hex(slot, image['type'], unsigned_hex, output_name, encrypt_key, boot_record=boot_record) first_image_result = hex_out is not None if hex_out: bin_out = '{0}.bin'.format(os.path.splitext(hex_out)[0]) if not erased_val: default_erased_val = self._default_erased_value( image_type, slot) ih_padding = int(default_erased_val, 0) upgrade_ih = IntelHex() upgrade_ih.padding = ih_padding upgrade_ih.loadfile(hex_out, 'hex') hex2bin(upgrade_ih, bin_out) bin2hex(bin_out, output_name, offset=int(image['address'])) os.remove(bin_out) if hex_out: result.append(hex_out) if encrypted_boot: self.replace_image_body(hex_file, unsigned_hex, ih_padding) if image_type: if ImageType.UPGRADE.name == image_type.upper(): os.remove(hex_file) result = tuple(result) if len(result) > 0 else None return result
def program(self): if not os.path.isfile( os.path.join(self.flora_path, DEVKIT_FIRMWARE_PATH + '.binary')): hex2bin( os.path.join(self.flora_path, DEVKIT_FIRMWARE_PATH + '.hex'), os.path.join(self.flora_path, DEVKIT_FIRMWARE_PATH + '.binary')) if not os.path.isfile( os.path.join(self.flora_path, COMBOARD_FIRMWARE_PATH + '.binary')): hex2bin( os.path.join(self.flora_path, COMBOARD_FIRMWARE_PATH + '.hex'), os.path.join(self.flora_path, COMBOARD_FIRMWARE_PATH + '.binary')) self.loader = Stm32Loader() self.loader.configuration['data_file'] = DEVKIT_FIRMWARE_PATH self.loader.configuration['port'] = self.bootloader.port.device self.loader.configuration['erase'] = True self.loader.configuration['write'] = True self.loader.configuration['verify'] = True self.loader.configuration['go_address'] = 0x08000000 self.loader.configuration['baud'] = 115200 # self.loader.connect() # Connecting manually, as a reset like in self.loader.connect() would not work on DevKit or ComBoard self.loader.bootloader = Stm32Bootloader() self.loader.bootloader.open( self.loader.configuration['port'], self.loader.configuration['baud'], self.loader.configuration['parity'], ) try: self.loader.bootloader.reset_from_system_memory() except Exception: print("Can't init. Ensure that BOOT0 is enabled and reset device") self.loader.bootloader.reset_from_flash() return try: device_id = self.loader.bootloader.get_id() self.loader.read_device_details() if device_id == 0x415: print("{} is DevKit.".format(self.bootloader.port.device)) self.loader.configuration['data_file'] = os.path.join( self.flora_path, DEVKIT_FIRMWARE_PATH + '.binary') elif device_id == 0x435: print("{} is ComBoard.".format(self.bootloader.port.device)) self.loader.configuration['data_file'] = os.path.join( self.flora_path, COMBOARD_FIRMWARE_PATH + '.binary') self.loader.perform_commands() if device_id == 0x435: self.loader.reset() finally: pass
def main(sdk_path, hex_file, key_priv, key_pub, key_aes, version, img_id, rlb_count, slot_size, pad, img_offset): """ Function consequentially performs operations with provided hex file and produces an encrypted and signed hex file for UPGRADE """ check_file_exist(key_priv) check_file_exist(key_pub) check_file_exist(key_aes) check_file_exist(hex_file) in_f = hex_file[:-4] + "_i.bin" out_f = hex_file[:-4] + "_o.bin" hex_file_final = get_final_hex_name(hex_file) print("Image UPGRADE:" + hex_file_final) # ih = IntelHex(hex_file) # img_start_addr = ih.start_addr['EIP'] hex2bin(hex_file, in_f) #bin_file) # $PYTHON $IMGTOOL sign --key $KEY --header-size $HEADER_SIZE --pad-header --align 8 --version $VERSION --image-id $ID --rollback_counter $ROLLBACK_COUNTER --slot-size $SLOT_SIZE --overwrite-only $binFileName $signedFileName is_file_created $signedFileName # call imgtool for signature process = subprocess.Popen([ sys.executable, sdk_path + "/imgtool/imgtool.py", "sign", "--key", key_priv, "--header-size", str(hex(HEADER_SIZE)), "--pad-header", "--align", "8", "--version", version, "--image-id", img_id, "--rollback_counter", rlb_count, "--slot-size", slot_size, "--overwrite-only", in_f, out_f ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, in_f, out_f) # AES # $PYTHON $(dirname "${IMGTOOL}")"/create_aesHeader.py" -k $KEY -p $KEY_DEV --key_to_encrypt "$KEY_AES" $AES_HEADER # call aesHeader for crypto header generation process = subprocess.Popen([ sys.executable, sdk_path + "/imgtool/create_aesHeader.py", "-k", key_priv, "-p", key_pub, "--key_to_encrypt", key_aes, AES_HEADER ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # catch stderr outputs stderr = process.communicate() rc = process.wait() check_file_exist(AES_HEADER) # aes_cipher.py script file should be in the same folder as imgtool.py # $PYTHON $(dirname "${IMGTOOL}")"/aes_cipher.py" -k $KEY_AES $signedFileName $aes_encryptedFileName # is_file_created $aes_encryptedFileName # encrypt signed image process = subprocess.Popen([ sys.executable, sdk_path + "/imgtool/aes_cipher.py", "-k", key_aes, out_f, in_f ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, out_f, in_f) # second part - obtain signed image from encrypted file - with padding - for staging area # $PYTHON $IMGTOOL sign --key $KEY --header-size $HEADER_SIZE --pad-header --align 8 --version $VERSION --image-id $ID --rollback_counter $ROLLBACK_COUNTER --slot-size $SLOT_SIZE --overwrite-only $PAD -a $AES_HEADER $aes_encryptedFileName $signedEncFileName # is_file_created $signedEncFileName # call imgtool for signature process = subprocess.Popen( [ sys.executable, sdk_path + "/imgtool/imgtool.py", "sign", "--key", key_priv, "--header-size", str(hex(HEADER_SIZE)), "--pad-header", "--align", "8", "--version", version, "--image-id", img_id, "--rollback_counter", rlb_count, "--slot-size", slot_size, "--overwrite-only", "--pad", "-a", AES_HEADER, in_f, out_f ], #bin_sig_enc, #bin_sig_enc_sig], stdout=subprocess.PIPE, stderr=subprocess.PIPE) manage_output(process, in_f, out_f) bin2hex(out_f, hex_file_final, int(img_offset)) os.remove(out_f) os.remove(AES_HEADER)
if not args: raise getopt.GetoptError('Hex file is not specified') if len(args) > 2: raise getopt.GetoptError('Too many arguments') except getopt.GetoptError: msg = sys.exc_info()[1] # current exception txt = 'ERROR: ' + str( msg) # that's required to get not-so-dumb result from 2to3 tool print(txt) print(usage) sys.exit(2) fin = args[0] if not os.path.isfile(fin): txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool print(txt) sys.exit(1) if len(args) == 2: fout = args[1] else: # write to stdout from intelhex import compat fout = compat.get_binary_stdout() from intelhex import hex2bin sys.exit(hex2bin(fin, fout, start, end, size, pad))
def inject_ids(new_school_id, new_hub_id, output_file_path="", clean=False): if len(new_school_id) != len(SCHOOL_ID): print("New school id length (%d) must match the old (%d)" % (len(new_school_id), len(SCHOOL_ID))) return -1 if len(new_hub_id) != len(HUB_ID): print("New hub id length (%d) must match the old (%d)" % (len(new_hub_id), len(HUB_ID))) return -1 if clean: print("Removing old hub file.") os.remove(package_directory + "/hexes/hub-not-combined.hex") if not os.path.isfile(package_directory + "/hexes/hub-not-combined.hex"): try: print("Copying latest hub file from: %s" % BUILD_FOLDER_PATH) copyfile(BUILD_FOLDER_PATH, package_directory + "/hexes/hub-not-combined.hex") except Exception as e: print("hub-combined-hex not available") with tempfile.NamedTemporaryFile() as hub_not_combined_modified_hex_file, \ tempfile.NamedTemporaryFile() as hub_not_combined_modified_bin_file, \ tempfile.NamedTemporaryFile() as temp_out_file: # first convert the uncombined hex file into bin hex_as_bin = hex2bin(package_directory + "/hexes/hub-not-combined.hex", hub_not_combined_modified_bin_file.name) # replace the old ids with the new. print("Replacing ids.") bin_data = hub_not_combined_modified_bin_file.readlines() hub_not_combined_modified_bin_file.seek(0) school_id_changed = False hub_id_changed = False for l in bin_data: try: new_l = re.sub(bytes(SCHOOL_ID, 'utf-8'), bytes(new_school_id, 'utf-8'), l) except: new_l = re.sub(SCHOOL_ID, new_school_id, l) if new_l != l: school_id_changed = True try: final_l = re.sub(bytes(HUB_ID, 'utf-8'), bytes(new_hub_id, 'utf-8'), new_l) except: final_l = re.sub(HUB_ID, new_hub_id, new_l) if final_l != new_l: hub_id_changed = True hub_not_combined_modified_bin_file.write(final_l) hub_not_combined_modified_bin_file.flush() if not school_id_changed: print("School id not found in bin!") exit(1) if not hub_id_changed: print("Hub id not found in bin!") exit(1) # then to hex bin2hex(hub_not_combined_modified_bin_file.name, hub_not_combined_modified_hex_file.name, 0x18000) replaced_hex = IntelHex(hub_not_combined_modified_hex_file.name) bootloader_hex = IntelHex(package_directory + "/hexes/BOOTLOADER.hex") softdevice_hex = IntelHex(package_directory + "/hexes/SOFTDEVICE.hex") replaced_hex.merge(bootloader_hex) replaced_hex.merge(softdevice_hex) # finally creating the final binary. if len(output_file_path): print("Creating final file: %s" % (output_file_path)) with open(output_file_path, 'w') as f: replaced_hex.write_hex_file(f.name) f.close() return 0 else: sio = StringIO() bio = BytesIO() try: #python 3 replaced_hex.write_hex_file(sio) return sio.getvalue() except: #python 2 replaced_hex.write_hex_file(bio) return bio.getvalue()