def send_start_dfu(self, program_mode, softdevice_size=0, bootloader_size=0, app_size=0): super(DfuTransportBle, self).send_start_dfu(program_mode, softdevice_size, bootloader_size, app_size) image_size_packet = DfuTransport.create_image_size_packet( softdevice_size, bootloader_size, app_size) self._send_event(DfuEvent.PROGRESS_EVENT, progress=0, log_message="Setting up transfer...") try: self._start_dfu(program_mode, image_size_packet) except IllegalStateException: # We got disconnected. Try to send Start DFU again in case of buttonless dfu. self.close() self.open() if not self.is_open(): raise IllegalStateException( "Failed to reopen transport backend.") self._start_dfu(program_mode, image_size_packet)
def get_vk_code(self): """ Get the verification key as code """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") vk = self.sk.get_verifying_key() vk_hex = binascii.hexlify(vk.to_string()) vk_x_separated = "" vk_x_str = vk_hex[0:64] for i in range(0, len(vk_x_str), 2): vk_x_separated += "0x" + vk_x_str[i:i + 2] + ", " vk_x_separated = vk_x_separated[:-2] vk_y_separated = "" vk_y_str = vk_hex[64:128] for i in range(0, len(vk_y_str), 2): vk_y_separated += "0x" + vk_y_str[i:i + 2] + ", " vk_y_separated = vk_y_separated[:-2] vk_code = "static uint8_t Qx[] = {{ {0} }};\n".format(vk_x_separated) vk_code += "static uint8_t Qy[] = {{ {0} }};".format(vk_y_separated) return vk_code
def _wait_for_response(self, opcode): """ Waits for self.response_opcode_received to be set to the expected opcode Will timeout after 10 seconds :param int opcode: The expected opcode :return: """ timeout = 40 start_time = datetime.now() while self.response_opcode_received != opcode: timed_out = datetime.now() - start_time > timedelta(0, timeout) if timed_out: log_message = "Timeout while waiting for response from device." self._send_event(DfuEvent.TIMEOUT_EVENT, log_message=log_message) raise NordicSemiException(log_message) if self.disconnected_event_received: log_message = "Disconnected from device." raise IllegalStateException(log_message) time.sleep(0.1) if self.last_error != DfuErrorCodeBle.SUCCESS: error_message = DfuErrorCodeBle.error_code_lookup(self.last_error) self._send_event(DfuEvent.ERROR_EVENT, log_message=error_message) raise NordicSemiException(error_message) self.response_opcode_received = None
def get_vk_code(self): """ Get the verification key as code """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") vk = self.sk.get_verifying_key() vk_hex = binascii.hexlify(vk.to_string()) vk_x_separated = "" vk_x_str = vk_hex[0:64] for i in xrange(0, len(vk_x_str), 2): vk_x_separated = "0x" + vk_x_str[i:i + 2] + ", " + vk_x_separated vk_y_separated = "" vk_y_str = vk_hex[64:128] for i in xrange(0, len(vk_y_str), 2): vk_y_separated = "0x" + vk_y_str[i:i + 2] + ", " + vk_y_separated vk_y_separated = vk_y_separated[:-2] vk_code = "static const uint8_t pk[] = {{ {0} }};".format( vk_x_separated + vk_y_separated) return vk_code + "\nstatic const nrf_crypto_key_t crypto_key_pk = { .p_le_data = (uint8_t *) pk, .len = sizeof(pk) };"
def get_vk_pem(self): """ Get the verification key as PEM """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") vk = self.sk.get_verifying_key() vk_pem = vk.to_pem() return vk_pem
def get_vk_hex(self): """ Get the verification key as hex """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") vk = self.sk.get_verifying_key() vk_hexlify = binascii.hexlify(vk.to_string()) vk_hex = "Verification key Qx: {0}\n".format(vk_hexlify[0:64]) vk_hex += "Verification key Qy: {0}".format(vk_hexlify[64:128]) return vk_hex
def sign(self, init_packet_data): """ Create signature for init package using P-256 curve and SHA-256 as hashing algorithm Returns R and S keys combined in a 64 byte array """ # Add assertion of init_packet if self.sk is None: raise IllegalStateException( "Can't save key. No key created/loaded") # Sign the init-packet signature = self.sk.sign(init_packet_data, hashfunc=hashlib.sha256, sigencode=sigencode_string) return signature
def get_vk(self, output_type): """ Get verification key (as hex, code or pem) """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") if output_type is None: raise InvalidArgumentException( "Invalid output type for signature.") elif output_type == 'hex': return self.get_vk_hex() elif output_type == 'code': return self.get_vk_code() elif output_type == 'pem': return self.get_vk_pem() else: raise InvalidArgumentException("Invalid argument. Can't get key")
def verify(self, init_packet, signature): """ Verify init packet """ # Add assertion of init_packet if self.sk is None: raise IllegalStateException( "Can't save key. No key created/loaded") vk = self.sk.get_verifying_key() # Verify init packet try: vk.verify(signature, init_packet, hashfunc=hashlib.sha256) except: return False return True
def get_sk_hex(self): """ Get the verification key as hex """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") sk_hexlify = binascii.hexlify(self.sk.to_string()) sk_hexlify_list = [] for i in xrange(len(sk_hexlify) - 2, -2, -2): sk_hexlify_list.append(sk_hexlify[i:i + 2]) sk_hexlify_list_str = ''.join(sk_hexlify_list) vk_hex = "Private (signing) key sk:\n{0}".format(sk_hexlify_list_str) return vk_hex
def get_sk_code(self): """ Get the verification key as code """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") sk_hex = binascii.hexlify(self.sk.to_string()) sk_x_separated = "" for i in xrange(0, len(sk_hex), 2): sk_x_separated = "0x" + sk_hex[i:i + 2] + ", " + sk_x_separated sk_x_separated = sk_x_separated[:-2] sk_code = "static const uint8_t sk[] = {{ {0} }};".format( sk_x_separated) return sk_code + "\nstatic const nrf_crypto_key_t crypto_key_sk = { .p_le_data = (uint8_t *) sk, .len = sizeof(sk) };"
def _wait_for_condition(self, condition_function, expected_condition_value=True, timeout=10, waiting_for="condition"): """ Waits for condition_function to be true Will timeout after 60 seconds :param function condition_function: The function we are waiting for to return true :param str timeout_message: Message that should be logged :return: """ start_time = datetime.now() while condition_function() != expected_condition_value: timeout_message = "Timeout while waiting for {0}.".format( waiting_for) timed_out = datetime.now() - start_time > timedelta(0, timeout) if timed_out: self._send_event(DfuEvent.TIMEOUT_EVENT, log_message=timeout_message) raise NordicSemiException(timeout_message) if not self.is_open(): log_message = "Disconnected from device while waiting for {0}.".format( waiting_for) raise IllegalStateException(log_message) sleep(0.1) if self.get_last_error() != DfuErrorCodeBle.SUCCESS: error_message = "Error occoured while waiting for {0}. Error response {1}." error_code = DfuErrorCodeBle.error_code_lookup( self.get_last_error()) error_message = error_message.format(waiting_for, error_code) self._send_event(DfuEvent.ERROR_EVENT, log_message=error_message) raise NordicSemiException(error_message)
def get_vk_hex(self): """ Get the verification key as hex """ if self.sk is None: raise IllegalStateException("Can't get key. No key created/loaded") vk = self.sk.get_verifying_key() vk_hexlify = binascii.hexlify(vk.to_string()) vk_hexlify_list = [] for i in xrange(len(vk_hexlify[0:64]) - 2, -2, -2): vk_hexlify_list.append(vk_hexlify[i:i + 2]) for i in xrange(len(vk_hexlify) - 2, 62, -2): vk_hexlify_list.append(vk_hexlify[i:i + 2]) vk_hexlify_list_str = ''.join(vk_hexlify_list) vk_hex = "Public (verification) key pk:\n{0}".format( vk_hexlify_list_str) return vk_hex
def send_start_dfu(self, program_mode, softdevice_size=0, bootloader_size=0, app_size=0): super(DfuTransportBle, self).send_start_dfu(program_mode, softdevice_size, bootloader_size, app_size) image_size_packet = DfuTransport.create_image_size_packet( softdevice_size, bootloader_size, app_size) self._send_event(DfuEvent.PROGRESS_EVENT, progress=0, log_message="Setting up transfer...") try: logging.debug("Sending 'START DFU' command") self.send_control_data(DfuOpcodesBle.START_DFU, chr(program_mode)) logging.debug("Sending image size") self.send_packet_data(image_size_packet) self._wait_for_response(DfuOpcodesBle.START_DFU) except IllegalStateException: #If at first you don't succeed, try, try again. self.close() self.disconnected_event_received = False self.open() if not self.is_open(): raise IllegalStateException( "Failed to open transport backend.") logging.debug("Sending 'START DFU' command") self.send_control_data(DfuOpcodesBle.START_DFU, chr(program_mode)) logging.debug("Sending image size") self.send_packet_data(image_size_packet) self._wait_for_response(DfuOpcodesBle.START_DFU)