def hbs_taskAgent( self, toAgent, task, key, id, expiry = None, investigationId = None ): # Make sure it's a valid agentid a = AgentId( toAgent ) if not a.isValid: return None if not type( task ) is rSequence: return None s = Signing( key ) r = rpcm( isHumanReadable = True, isDebug = True ) tags = Symbols() if investigationId is not None and '' != investigationId: task.addStringA( tags.hbs.INVESTIGATION_ID, investigationId ) toSign = ( rSequence().addSequence( tags.base.HCP_ID, rSequence().addInt8( tags.base.HCP_ID_ORG, a.org ) .addInt8( tags.base.HCP_ID_SUBNET, a.subnet ) .addInt32( tags.base.HCP_ID_UNIQUE, a.unique ) .addInt8( tags.base.HCP_ID_PLATFORM, a.platform ) .addInt8( tags.base.HCP_ID_CONFIG, a.config ) ) .addSequence( tags.hbs.NOTIFICATION, task ) .addInt32( tags.hbs.NOTIFICATION_ID, id ) ) if None != expiry: toSign.addTimestamp( tags.base.EXPIRY, int( expiry ) ) toSign = r.serialise( toSign ) sig = s.sign( toSign ) final = r.serialise( rSequence().addBuffer( tags.base.BINARY, toSign ) .addBuffer( tags.base.SIGNATURE, sig ) ) return self._query( 'hbs.task_agent', { 'task' : final, 'agentid' : str( a ) } )
def __init__(self, cert_file, password, provozovna=1, pokladna='lidicka', testing=True, eet_url='https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3'): self._cert_file = cert_file self._testing = testing self._pokladna = pokladna self._provozovna = provozovna self._eet_url = eet_url self._signing = Signing(cert_file, password) components = self._signing.get_cert_subject().get_components() cn = [x for x in components if x[0] == b'CN'] assert(len(cn) == 1) self._dic = cn[0][1].decode('utf8') print('DIC: %s' % self._dic)
def hbs_taskAgent(self, toAgent, task, key, id, expiry=None, investigationId=None): # Make sure it's a valid agentid a = AgentId(toAgent) if not type(task) is rSequence: return None s = Signing(key) r = rpcm(isHumanReadable=True, isDebug=True) tags = Symbols() if investigationId is not None and '' != investigationId: task.addStringA(tags.hbs.INVESTIGATION_ID, investigationId) toSign = (rSequence().addSequence( tags.base.HCP_IDENT, rSequence().addBuffer( tags.base.HCP_SENSOR_ID, (a.sensor_id if a.sensor_id is not None else self.empty_uuid).bytes).addBuffer( tags.base.HCP_ORG_ID, (a.org_id if a.org_id is not None else self.empty_uuid).bytes).addBuffer( tags.base.HCP_INSTALLER_ID, (a.ins_id if a.ins_id is not None else self.empty_uuid).bytes).addInt32( tags.base.HCP_ARCHITECTURE, a.architecture if a.architecture is not None else 0).addInt32( tags.base.HCP_PLATFORM, a.platform if a.platform is not None else 0)).addSequence( tags.hbs.NOTIFICATION, task).addInt32(tags.hbs.NOTIFICATION_ID, id)) if None != expiry: toSign.addTimestamp(tags.base.EXPIRY, int(expiry)) toSign = r.serialise(toSign) sig = s.sign(toSign) final = r.serialise(rSequence().addBuffer( tags.base.BINARY, toSign).addBuffer(tags.base.SIGNATURE, sig)) return self._query('hbs.task_agent', { 'task': final, 'aid': str(a), 'expiry': expiry })
def hbs_taskAgent(self, toAgent, task, key, id, expiry=None, investigationId=None): # Make sure it's a valid agentid a = AgentId(toAgent) if not a.isValid: return None if not type(task) is rSequence: return None s = Signing(key) r = rpcm(isHumanReadable=True, isDebug=True) tags = Symbols() if investigationId is not None and '' != investigationId: task.addStringA(tags.hbs.INVESTIGATION_ID, investigationId) toSign = (rSequence().addSequence( tags.base.HCP_ID, rSequence().addInt8(tags.base.HCP_ID_ORG, a.org).addInt8( tags.base.HCP_ID_SUBNET, a.subnet).addInt32(tags.base.HCP_ID_UNIQUE, a.unique).addInt8( tags.base.HCP_ID_PLATFORM, a.platform).addInt8( tags.base.HCP_ID_CONFIG, a.config)).addSequence( tags.hbs.NOTIFICATION, task).addInt32(tags.hbs.NOTIFICATION_ID, id)) if None != expiry: toSign.addTimestamp(tags.base.EXPIRY, int(expiry)) toSign = r.serialise(toSign) sig = s.sign(toSign) final = r.serialise(rSequence().addBuffer( tags.base.BINARY, toSign).addBuffer(tags.base.SIGNATURE, sig)) return self._query('hbs.task_agent', { 'task': final, 'agentid': str(a), 'expiry': expiry })
def generate_package(self, filename, preserve_work_directory=False): """ Generates a Nordic DFU package. The package is a zip file containing firmware(s) and metadata required for Nordic DFU applications to perform DFU onn nRF5X devices. :param str filename: Filename for generated package. :param bool preserve_work_directory: True to preserve the temporary working directory. Useful for debugging of a package, and if the user wants to look at the generated package without having to unzip it. :return: None """ work_directory = self.__create_temp_workspace() if Package._is_bootloader_softdevice_combination(self.firmwares_data): # Removing softdevice and bootloader data from dictionary and adding the combined later softdevice_fw_data = self.firmwares_data.pop(HexType.SOFTDEVICE) bootloader_fw_data = self.firmwares_data.pop(HexType.BOOTLOADER) softdevice_fw_name = softdevice_fw_data[ FirmwareKeys.FIRMWARE_FILENAME] bootloader_fw_name = bootloader_fw_data[ FirmwareKeys.FIRMWARE_FILENAME] new_filename = "sd_bl.bin" sd_bl_file_path = os.path.join(work_directory, new_filename) nrf_hex = nRFHex(softdevice_fw_name, bootloader_fw_name) nrf_hex.tobinfile(sd_bl_file_path) softdevice_size = nrf_hex.size() bootloader_size = nrf_hex.bootloadersize() self.__add_firmware_info( HexType.SD_BL, sd_bl_file_path, softdevice_fw_data[FirmwareKeys.INIT_PACKET_DATA], softdevice_size, bootloader_size) for key, firmware_data in self.firmwares_data.iteritems(): # Normalize the firmware file and store it in the work directory firmware_data[FirmwareKeys.BIN_FILENAME] = \ Package.normalize_firmware_to_bin(work_directory, firmware_data[FirmwareKeys.FIRMWARE_FILENAME]) # Calculate the hash for the .bin file located in the work directory bin_file_path = os.path.join( work_directory, firmware_data[FirmwareKeys.BIN_FILENAME]) firmware_hash = Package.calculate_sha256_hash(bin_file_path) bin_length = int(Package.calculate_file_size(bin_file_path)) sd_size = 0 bl_size = 0 app_size = 0 if key == HexType.APPLICATION: app_size = bin_length elif key == HexType.SOFTDEVICE: sd_size = bin_length elif key == HexType.BOOTLOADER: bl_size = bin_length elif key == HexType.SD_BL: bl_size = firmware_data[FirmwareKeys.BL_SIZE] sd_size = firmware_data[FirmwareKeys.SD_SIZE] init_packet = InitPacketPB( hash_bytes=firmware_hash, dfu_type=HexTypeToInitPacketFwTypemap[key], hash_type=HashTypes.SHA256, app_size=app_size, sd_size=sd_size, bl_size=bl_size, fw_version=firmware_data[FirmwareKeys.INIT_PACKET_DATA][ PacketField.APP_VERSION], hw_version=firmware_data[FirmwareKeys.INIT_PACKET_DATA][ PacketField.DEVICE_REVISION], sd_req=firmware_data[FirmwareKeys.INIT_PACKET_DATA][ PacketField.REQUIRED_SOFTDEVICES_ARRAY]) signer = Signing() signer.load_key(self.key_file) signature = signer.sign(init_packet.get_init_command_bytes()) init_packet.set_signature(signature, SigningTypes.ECDSA_P256_SHA256) # Store the .dat file in the work directory init_packet_filename = firmware_data[ FirmwareKeys.BIN_FILENAME].replace(".bin", ".dat") with open(os.path.join(work_directory, init_packet_filename), 'wb') as init_packet_file: init_packet_file.write(init_packet.get_init_packet_pb_bytes()) firmware_data[FirmwareKeys.DAT_FILENAME] = \ init_packet_filename # Store the manifest to manifest.json manifest = self.create_manifest() with open(os.path.join(work_directory, Package.MANIFEST_FILENAME), "w") as manifest_file: manifest_file.write(manifest) # Package the work_directory to a zip file Package.create_zip_package(work_directory, filename) # Delete the temporary directory if not preserve_work_directory: shutil.rmtree(work_directory)
class EET: def __init__(self, cert_file, password, provozovna=1, pokladna='lidicka', testing=True, eet_url='https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3'): self._cert_file = cert_file self._testing = testing self._pokladna = pokladna self._provozovna = provozovna self._eet_url = eet_url self._signing = Signing(cert_file, password) components = self._signing.get_cert_subject().get_components() cn = [x for x in components if x[0] == b'CN'] assert(len(cn) == 1) self._dic = cn[0][1].decode('utf8') print('DIC: %s' % self._dic) def create_payment(self, poradi, amount, first=True, test=True): header = TrzbaHeader(first, test) return Trzba(header, poradi, self._dic, self._provozovna, self._pokladna, amount) def send_payment(self, payment): trzba_xml = payment.xml(self._signing) soap_xml = wsse.soap_wsse(trzba_xml, self._signing) soap_string = etree.tostring(soap_xml) open('/tmp/y.xml', 'wb').write(soap_string) resp = requests.post(self._eet_url, soap_string) resp.raise_for_status() try: reply = etree.XML(resp.content) # print(etree.tostring(reply, pretty_print=4)) header = utils.find_node(reply, 'Hlavicka', NS_EET_URL) except etree.XMLSyntaxError as e: raise eet_exceptions.BadResponse('Failed to parse response from server (%s)'%(str(e))) except eet_exceptions.NodeNotFound: raise eet_exceptions.BadResponse('Failed to process response - missing node Hlavicka') try: confirmation = utils.find_node(reply, 'Potvrzeni', NS_EET_URL) orig_bkp = utils.find_node(trzba_xml, 'bkp') bkp = header.get('bkp') # print('received bkp: %s, original: %s' % (bkp, orig_bkp.text)) if bkp != orig_bkp.text: raise eet_exceptions.BadResponse('Wrong BKP in response!') response = { 'date_received': header.get('dat_prij'), 'uuid_reply': header.get('uuid_zpravy'), 'bkp': bkp, 'fik': confirmation.get('fik'), 'test': confirmation.get('test')} except eet_exceptions.NodeNotFound: try: error = utils.find_node(reply, 'Chyba', NS_EET_URL) response = { 'date_rejected': header.get('dat_odmit'), 'fik': None, 'test': error.get('test'), 'kod':error.get('kod'), 'message': error.text} except eet_exceptions.NodeNotFound: raise eet_exceptions.BadResponse('Failed to get data from server response') return response
def generate_package(self, filename, preserve_work_directory=False): """ Generates a Nordic DFU package. The package is a zip file containing firmware(s) and metadata required for Nordic DFU applications to perform DFU onn nRF5X devices. :param str filename: Filename for generated package. :param bool preserve_work_directory: True to preserve the temporary working directory. Useful for debugging of a package, and if the user wants to look at the generated package without having to unzip it. :return: None """ work_directory = self.__create_temp_workspace() if Package._is_bootloader_softdevice_combination(self.firmwares_data): # Removing softdevice and bootloader data from dictionary and adding the combined later softdevice_fw_data = self.firmwares_data.pop(HexType.SOFTDEVICE) bootloader_fw_data = self.firmwares_data.pop(HexType.BOOTLOADER) softdevice_fw_name = softdevice_fw_data[FirmwareKeys.FIRMWARE_FILENAME] bootloader_fw_name = bootloader_fw_data[FirmwareKeys.FIRMWARE_FILENAME] new_filename = "sd_bl.bin" sd_bl_file_path = os.path.join(work_directory, new_filename) nrf_hex = nRFHex(softdevice_fw_name, bootloader_fw_name) nrf_hex.tobinfile(sd_bl_file_path) softdevice_size = nrf_hex.size() bootloader_size = nrf_hex.bootloadersize() self.__add_firmware_info( HexType.SD_BL, sd_bl_file_path, softdevice_fw_data[FirmwareKeys.INIT_PACKET_DATA], softdevice_size, bootloader_size, ) for key in self.firmwares_data: firmware = self.firmwares_data[key] # Normalize the firmware file and store it in the work directory firmware[FirmwareKeys.BIN_FILENAME] = Package.normalize_firmware_to_bin( work_directory, firmware[FirmwareKeys.FIRMWARE_FILENAME] ) # Calculate the hash for the .bin file located in the work directory bin_file_path = os.path.join(work_directory, firmware[FirmwareKeys.BIN_FILENAME]) init_packet_data = firmware[FirmwareKeys.INIT_PACKET_DATA] if self.dfu_ver <= 0.5: firmware_hash = Package.calculate_crc16(bin_file_path) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_CRC16] = firmware_hash elif self.dfu_ver == 0.6: init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_USES_CRC16 firmware_hash = Package.calculate_crc16(bin_file_path) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_CRC16] = firmware_hash elif self.dfu_ver == 0.7: init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_USES_HASH init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_LENGTH] = int( Package.calculate_file_size(bin_file_path) ) firmware_hash = Package.calculate_sha256_hash(bin_file_path) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_HASH] = firmware_hash elif self.dfu_ver == 0.8: init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_EXT_USES_ECDS firmware_hash = Package.calculate_sha256_hash(bin_file_path) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_LENGTH] = int( Package.calculate_file_size(bin_file_path) ) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_HASH] = firmware_hash temp_packet = self._create_init_packet(firmware) signer = Signing() signer.load_key(self.key_file) signature = signer.sign(temp_packet) init_packet_data[PacketField.NORDIC_PROPRIETARY_OPT_DATA_INIT_PACKET_ECDS] = signature # Store the .dat file in the work directory init_packet = self._create_init_packet(firmware) init_packet_filename = firmware[FirmwareKeys.BIN_FILENAME].replace(".bin", ".dat") with open(os.path.join(work_directory, init_packet_filename), "wb") as init_packet_file: init_packet_file.write(init_packet) firmware[FirmwareKeys.DAT_FILENAME] = init_packet_filename # Store the manifest to manifest.json manifest = self.create_manifest() with open(os.path.join(work_directory, Package.MANIFEST_FILENAME), "w") as manifest_file: manifest_file.write(manifest) # Package the work_directory to a zip file Package.create_zip_package(work_directory, filename) # Delete the temporary directory if not preserve_work_directory: shutil.rmtree(work_directory)
def do_login( self, s ): '''Login to the BE using credentials stored in a config file.''' parser = self.getParser( 'login' ) parser.add_argument( 'configFile', type = argparse.FileType( 'r' ), help = 'config file specifying the endpoint and token to use' ) parser.add_argument( '-k', '--key', required = False, default = None, #type = argparse.FileType( 'r' ), type = str, help = 'key to use to sign hbs tasks', dest = 'key' ) arguments = self.parse( parser, s ) if arguments is not None: try: config = json.loads( arguments.configFile.read() ) except: print( "Invalid config file format (JSON): %s" % traceback.format_exc() ) return if 'beach_config' not in config or 'token' not in config: print( "Missing endpoint or token in config." ) return _ = os.getcwd() os.chdir( os.path.dirname( __file__ ) ) self.be = BEAdmin( config[ 'beach_config' ], config[ 'token' ] ) os.chdir( _ ) remoteTime = self.be.testConnection() if remoteTime.isTimedOut: print( "Endpoint did not respond." ) return if 'pong' not in remoteTime.data: print( "Endpoint responded with invalid data." ) return if arguments.key is not None: if os.path.isfile( arguments.key ): try: password = getpass.getpass() print( "...decrypting key..." ) # There are weird problems with pexpect and newlines and binary, so # we have to brute force it a bit for i in range( 0, 30 ): proc = pexpect.spawn( 'openssl aes-256-cbc -d -in %s' % arguments.key ) proc.expect( [ 'enter aes-256-cbc decryption password: *' ] ) proc.sendline( password ) proc.expect( "\r\n" ) proc.expect( ".*" ) self.hbsKey = proc.match.group( 0 ).replace( "\r\n", "\n" ) try: testSign = Signing( self.hbsKey ) testSig = testSign.sign( 'a' ) if testSig is not None: break except: self.hbsKey = None if self.hbsKey is not None: print( "success, authenticated!" ) else: print( "error loading key, bad key format or password?" ) except: self.hbsKey = None print( "error getting cloud key: %s" % traceback.format_exc() ) if self.hbsKey is not None and 'bad decrypt' in self.hbsKey: print( "Invalid password" ) self.hbsKey = None else: print( "Invalid key file: %s." % arguments.key ) self.hbsKey = None else: self.hbsKey = None remoteTime = remoteTime.data.get( 'pong', 0 ) print( "Successfully logged in." ) print( "Remote endpoint time: %s." % remoteTime ) self.user = config[ 'token' ].split( '/' )[ 0 ] self.updatePrompt()
def do_login( self, s ): '''Login to the BE using credentials stored in a config file.''' parser = self.getParser( 'login' ) parser.add_argument( 'configFile', type = argparse.FileType( 'r' ), help = 'config file specifying the endpoint and token to use' ) parser.add_argument( '-k', '--key', required = False, default = None, #type = argparse.FileType( 'r' ), type = str, help = 'key to use to sign hbs tasks', dest = 'key' ) arguments = self.parse( parser, s ) if arguments is not None: try: config = json.loads( arguments.configFile.read() ) except: self.outputString( "Invalid config file format (JSON): %s" % traceback.format_exc() ) return if 'beach_config' not in config or 'token' not in config: self.outputString( "Missing endpoint or token in config." ) return _ = os.getcwd() os.chdir( os.path.dirname( __file__ ) ) self.connectWithConfig( config[ 'beach_config' ], config[ 'token' ] ) os.chdir( _ ) remoteTime = self.be.testConnection() if remoteTime.isTimedOut: self.outputString( "Endpoint did not respond." ) return if 'pong' not in remoteTime.data: self.outputString( "Endpoint responded with invalid data." ) return if arguments.key is not None: if os.path.isfile( arguments.key ): try: password = getpass.getpass() self.outputString( "...decrypting key..." ) # There are weird problems with pexpect and newlines and binary, so # we have to brute force it a bit for i in range( 0, 30 ): proc = pexpect.spawn( 'openssl aes-256-cbc -d -in %s' % arguments.key ) proc.expect( [ 'enter aes-256-cbc decryption password: *' ] ) proc.sendline( password ) proc.expect( "\r\n" ) proc.expect( ".*" ) self.loadKey( proc.match.group( 0 ).replace( "\r\n", "\n" ) ) try: testSign = Signing( self.hbsKey ) testSig = testSign.sign( 'a' ) if testSig is not None: break except: self.hbsKey = None if self.hbsKey is not None: self.outputString( "success, authenticated!" ) else: self.outputString( "error loading key, bad key format or password?" ) except: self.hbsKey = None self.outputString( "error getting cloud key: %s" % traceback.format_exc() ) if self.hbsKey is not None and 'bad decrypt' in self.hbsKey: self.outputString( "Invalid password" ) self.hbsKey = None else: self.outputString( "Invalid key file: %s." % arguments.key ) self.hbsKey = None else: self.hbsKey = None remoteTime = remoteTime.data.get( 'pong', 0 ) self.outputString( "Successfully logged in." ) self.outputString( "Remote endpoint time: %s." % remoteTime ) self.user = config[ 'token' ].split( '/' )[ 0 ] self.updatePrompt()
def generate_package(self, filename, preserve_work_dir=False): """ Generates a Nordic DFU package. The package is a zip file containing firmware(s) and metadata required for Nordic DFU applications to perform DFU onn nRF5X devices. :param str filename: Filename for generated package. :param bool preserve_work_dir: True to preserve the temporary working directory. Useful for debugging of a package, and if the user wants to look at the generated package without having to unzip it. :return: None """ self.zip_file = filename self.work_dir = self.__create_temp_workspace() if Package._is_bootloader_softdevice_combination(self.firmwares_data): # Removing softdevice and bootloader data from dictionary and adding the combined later softdevice_fw_data = self.firmwares_data.pop(HexType.SOFTDEVICE) bootloader_fw_data = self.firmwares_data.pop(HexType.BOOTLOADER) softdevice_fw_name = softdevice_fw_data[FirmwareKeys.FIRMWARE_FILENAME] bootloader_fw_name = bootloader_fw_data[FirmwareKeys.FIRMWARE_FILENAME] new_filename = "sd_bl.bin" sd_bl_file_path = os.path.join(self.work_dir, new_filename) nrf_hex = nRFHex(softdevice_fw_name, bootloader=bootloader_fw_name) nrf_hex.tobinfile(sd_bl_file_path) softdevice_size = nrf_hex.size() bootloader_size = nrf_hex.bootloadersize() self.__add_firmware_info(firmware_type=HexType.SD_BL, firmware_version=bootloader_fw_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.FW_VERSION], # use bootloader version in combination with SD filename=sd_bl_file_path, init_packet_data=softdevice_fw_data[FirmwareKeys.INIT_PACKET_DATA], sd_size=softdevice_size, bl_size=bootloader_size) elif Package._is_application_softdevice_combination(self.firmwares_data): # Removing softdevice and bootloader data from dictionary and adding the combined later softdevice_fw_data = self.firmwares_data.pop(HexType.SOFTDEVICE) application_fw_data = self.firmwares_data.pop(HexType.APPLICATION) softdevice_fw_name = softdevice_fw_data[FirmwareKeys.FIRMWARE_FILENAME] application_fw_name = application_fw_data[FirmwareKeys.FIRMWARE_FILENAME] application_address = application_fw_data[FirmwareKeys.APP_ADDR] new_filename = "sd_app.bin" sd_app_file_path = os.path.join(self.work_dir, new_filename) nrf_hex = nRFHex(softdevice_fw_name, application=application_fw_name) nrf_hex.tobinfile(sd_app_file_path) softdevice_size = nrf_hex.size() application_size = nrf_hex.applicationsize() self.__add_firmware_info(firmware_type=HexType.SD_APP, firmware_version=application_fw_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.FW_VERSION], # use application version in combination with SD filename=sd_app_file_path, init_packet_data=softdevice_fw_data[FirmwareKeys.INIT_PACKET_DATA], sd_size=softdevice_size, app_size=application_size, app_addr=application_address) for key, firmware_data in self.firmwares_data.iteritems(): # Normalize the firmware file and store it in the work directory firmware_data[FirmwareKeys.BIN_FILENAME] = \ Package.normalize_firmware_to_bin(self.work_dir, firmware_data[FirmwareKeys.FIRMWARE_FILENAME]) # Calculate the hash for the .bin file located in the work directory bin_file_path = os.path.join(self.work_dir, firmware_data[FirmwareKeys.BIN_FILENAME]) firmware_hash = Package.calculate_sha256_hash(bin_file_path) bin_length = int(Package.calculate_file_size(bin_file_path)) sd_size = 0 bl_size = 0 app_size = 0 app_addr = 0 if key == HexType.APPLICATION: app_size = bin_length elif key == HexType.SOFTDEVICE: sd_size = bin_length elif key == HexType.BOOTLOADER: bl_size = bin_length elif key == HexType.SD_BL: bl_size = firmware_data[FirmwareKeys.BL_SIZE] sd_size = firmware_data[FirmwareKeys.SD_SIZE] elif key == HexType.SD_APP: app_size = firmware_data[FirmwareKeys.APP_SIZE] sd_size = firmware_data[FirmwareKeys.SD_SIZE] app_addr = firmware_data[FirmwareKeys.APP_ADDR] init_packet = InitPacketPB( from_bytes=None, hash_bytes=firmware_hash, hash_type=HashTypes.SHA256, dfu_type=HexTypeToInitPacketFwTypemap[key], is_debug=firmware_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.DEBUG_MODE], fw_version=firmware_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.FW_VERSION], hw_version=firmware_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.HW_VERSION], sd_size=sd_size, app_size=app_size, app_addr=app_addr, bl_size=bl_size, sd_req=firmware_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.REQUIRED_SOFTDEVICES_ARRAY]) signer = Signing() signer.load_key(self.key_file) signature = signer.sign(init_packet.get_init_command_bytes()) init_packet.set_signature(signature, SigningTypes.ECDSA_P256_SHA256) # Store the .dat file in the work directory init_packet_filename = firmware_data[FirmwareKeys.BIN_FILENAME].replace(".bin", ".dat") with open(os.path.join(self.work_dir, init_packet_filename), 'wb') as init_packet_file: init_packet_file.write(init_packet.get_init_packet_pb_bytes()) firmware_data[FirmwareKeys.DAT_FILENAME] = \ init_packet_filename # Store the manifest to manifest.json manifest = self.create_manifest() with open(os.path.join(self.work_dir, Package.MANIFEST_FILENAME), "w") as manifest_file: manifest_file.write(manifest) # Package the work_dir to a zip file Package.create_zip_package(self.work_dir, filename) # Delete the temporary directory self.rm_work_dir(preserve_work_dir)
def do_login(self, s): """Login to the BE using credentials stored in a config file.""" parser = self.getParser("login") parser.add_argument( "configFile", type=argparse.FileType("r"), help="config file specifying the endpoint and token to use" ) parser.add_argument( "-k", "--key", required=False, default=None, # type = argparse.FileType( 'r' ), type=str, help="key to use to sign hbs tasks", dest="key", ) arguments = self.parse(parser, s) if arguments is not None: try: config = json.loads(arguments.configFile.read()) except: print("Invalid config file format (JSON): %s" % traceback.format_exc()) return if "beach_config" not in config or "token" not in config: print("Missing endpoint or token in config.") return _ = os.getcwd() os.chdir(os.path.dirname(__file__)) self.be = BEAdmin(config["beach_config"], config["token"]) os.chdir(_) remoteTime = self.be.testConnection() if remoteTime.isTimedOut: print("Endpoint did not respond.") return if "pong" not in remoteTime.data: print("Endpoint responded with invalid data.") return if arguments.key is not None: if os.path.isfile(arguments.key): try: password = getpass.getpass() print("...decrypting key...") # There are weird problems with pexpect and newlines and binary, so # we have to brute force it a bit for i in range(0, 30): proc = pexpect.spawn("openssl aes-256-cbc -d -in %s" % arguments.key) proc.expect(["enter aes-256-cbc decryption password: *"]) proc.sendline(password) proc.expect("\r\n") proc.expect(".*") self.hbsKey = proc.match.group(0).replace("\r\n", "\n") try: testSign = Signing(self.hbsKey) testSig = testSign.sign("a") if testSig is not None: break except: self.hbsKey = None if self.hbsKey is not None: print("success, authenticated!") else: print("error loading key, bad key format or password?") except: self.hbsKey = None print("error getting cloud key: %s" % traceback.format_exc()) if self.hbsKey is not None and "bad decrypt" in self.hbsKey: print("Invalid password") self.hbsKey = None else: print("Invalid key file: %s." % arguments.key) self.hbsKey = None else: self.hbsKey = None remoteTime = remoteTime.data.get("pong", 0) print("Successfully logged in.") print("Remote endpoint time: %s." % remoteTime) self.user = config["token"].split("/")[0] self.updatePrompt()
def generate_package(self, filename, preserve_work_directory=False): """ Generates a Nordic DFU package. The package is a zip file containing firmware(s) and metadata required for Nordic DFU applications to perform DFU onn nRF5X devices. :param str filename: Filename for generated package. :param bool preserve_work_directory: True to preserve the temporary working directory. Useful for debugging of a package, and if the user wants to look at the generated package without having to unzip it. :return: None """ work_directory = self.__create_temp_workspace() if Package._is_bootloader_softdevice_combination(self.firmwares_data): # Removing softdevice and bootloader data from dictionary and adding the combined later softdevice_fw_data = self.firmwares_data.pop(HexType.SOFTDEVICE) bootloader_fw_data = self.firmwares_data.pop(HexType.BOOTLOADER) softdevice_fw_name = softdevice_fw_data[ FirmwareKeys.FIRMWARE_FILENAME] bootloader_fw_name = bootloader_fw_data[ FirmwareKeys.FIRMWARE_FILENAME] new_filename = "sd_bl.bin" sd_bl_file_path = os.path.join(work_directory, new_filename) nrf_hex = nRFHex(softdevice_fw_name, bootloader_fw_name) nrf_hex.tobinfile(sd_bl_file_path) softdevice_size = nrf_hex.size() bootloader_size = nrf_hex.bootloadersize() self.__add_firmware_info( HexType.SD_BL, sd_bl_file_path, softdevice_fw_data[FirmwareKeys.INIT_PACKET_DATA], softdevice_size, bootloader_size) for key in self.firmwares_data: firmware = self.firmwares_data[key] # Normalize the firmware file and store it in the work directory firmware[FirmwareKeys.BIN_FILENAME] = \ Package.normalize_firmware_to_bin(work_directory, firmware[FirmwareKeys.FIRMWARE_FILENAME]) # Calculate the hash for the .bin file located in the work directory bin_file_path = os.path.join(work_directory, firmware[FirmwareKeys.BIN_FILENAME]) init_packet_data = firmware[FirmwareKeys.INIT_PACKET_DATA] if self.dfu_ver <= 0.5: firmware_hash = Package.calculate_crc16(bin_file_path) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_CRC16] = firmware_hash elif self.dfu_ver == 0.6: init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_USES_CRC16 firmware_hash = Package.calculate_crc16(bin_file_path) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_CRC16] = firmware_hash elif self.dfu_ver == 0.7: init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_USES_HASH init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_LENGTH] = int( Package.calculate_file_size(bin_file_path)) firmware_hash = Package.calculate_sha256_hash(bin_file_path) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_HASH] = firmware_hash elif self.dfu_ver == 0.8: init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_EXT_PACKET_ID] = INIT_PACKET_EXT_USES_ECDS firmware_hash = Package.calculate_sha256_hash(bin_file_path) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_LENGTH] = int( Package.calculate_file_size(bin_file_path)) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_FIRMWARE_HASH] = firmware_hash temp_packet = self._create_init_packet(firmware) signer = Signing() signer.load_key(self.key_file) signature = signer.sign(temp_packet) init_packet_data[ PacketField. NORDIC_PROPRIETARY_OPT_DATA_INIT_PACKET_ECDS] = signature # Store the .dat file in the work directory init_packet = self._create_init_packet(firmware) init_packet_filename = firmware[FirmwareKeys.BIN_FILENAME].replace( ".bin", ".dat") with open(os.path.join(work_directory, init_packet_filename), 'wb') as init_packet_file: init_packet_file.write(init_packet) firmware[FirmwareKeys.DAT_FILENAME] = \ init_packet_filename # Store the manifest to manifest.json manifest = self.create_manifest() with open(os.path.join(work_directory, Package.MANIFEST_FILENAME), "w") as manifest_file: manifest_file.write(manifest) # Package the work_directory to a zip file Package.create_zip_package(work_directory, filename) # Delete the temporary directory if not preserve_work_directory: shutil.rmtree(work_directory)