def __ecu_reset_wrapper(args): """Wrapper used to initiate ECU Reset""" arb_id_request = args.src arb_id_response = args.dst reset_type = args.reset_type timeout = args.timeout print( "Sending ECU reset, type 0x{0:02x} to arbitration ID {1} (0x{1:02x})". format(reset_type, arb_id_request)) try: response = ecu_reset(arb_id_request, arb_id_response, reset_type, timeout) except ValueError as e: print("ValueError: {0}".format(e)) return # Decode response if response is None: print("No response was received") else: response_length = len(response) if response_length == 0: # Empty response print("Received empty response") elif response_length == 1: # Invalid response length print( "Received response [{0:02x}] (1 byte), expected at least 2 bytes" .format(response[0], len(response))) elif Iso14229_1.is_positive_response(response): # Positive response handling response_service_id = response[0] subfunction = response[1] expected_response_id = Iso14229_1.get_service_response_id( Services.EcuReset.service_id) if response_service_id == expected_response_id and subfunction == reset_type: # Positive response print("Received positive response") if response_length > 2: # Additional data can be seconds left to reset (powerDownTime) or manufacturer specific additional_data = list_to_hex_str(response[2:], ",") print("Response contains additional data: [{0}]".format( additional_data)) else: # Service and/or subfunction mismatch print( "Response service ID 0x{0:02x} and subfunction 0x{1:02x} do not match expected values " "0x{2:02x} and 0x{3:02x}".format(response_service_id, subfunction, expected_response_id, reset_type)) else: # Negative response handling nrc = response[1] nrc_description = NRC_NAMES.get(nrc, "Unknown NRC value") print( "Received negative response code (NRC) 0x{0:02x}: {1}".format( nrc, nrc_description))
def __security_seed_wrapper(args): """Wrapper used to initiate security seed dump""" arb_id_request = args.src arb_id_response = args.dst reset_type = args.reset session_type = args.sess_type level = args.sec_level num_seeds = args.num reset_delay = args.delay seed_list = [] try: print("Security seed dump started. Press Ctrl+C to stop.\n") while num_seeds > len(seed_list) or num_seeds == 0: # Extended diagnostics response = extended_session(arb_id_request, arb_id_response, session_type) if not Iso14229_1.is_positive_response(response): print("Unable to enter extended session. Retrying...\n") continue # Request seed response = request_seed(arb_id_request, arb_id_response, level, None, None) if response is None: print("\nInvalid response") elif Iso14229_1.is_positive_response(response): seed_list.append(list_to_hex_str(response[2:])) print("Seed received: {}\t(Total captured: {})".format( list_to_hex_str(response[2:]), len(seed_list)), end="\r") stdout.flush() else: print_negative_response(response) break if reset_type: ecu_reset(arb_id_request, arb_id_response, reset_type, None) time.sleep(reset_delay) except KeyboardInterrupt: print("Interrupted by user.") except ValueError as e: print(e) return if len(seed_list) > 0: print("\n") print("Security Access Seeds captured:") for seed in seed_list: print(seed)
def send_key(arb_id_request, arb_id_response, level, key, timeout): """ Sends an Send key message to 'arb_id_request'. Returns the first response received from 'arb_id_response' within 'timeout' seconds or None otherwise. :param arb_id_request: arbitration ID for requests :param arb_id_response: arbitration ID for responses :param level: vehicle manufacturer specific access level to send key for :param key: key to transmit :param timeout: seconds to wait for response before timeout, or None for default UDS timeout :type arb_id_request: int :type arb_id_response: int :type level: int :type key: [int] :type timeout: float or None :return: list of response byte values on success, None otherwise :rtype [int] or None """ # Sanity checks if not Services.SecurityAccess.RequestSeedOrSendKey().is_valid_send_key_level(level): raise ValueError("Invalid send key level") if isinstance(timeout, float) and timeout < 0.0: raise ValueError("timeout value ({0}) cannot be negative".format(timeout)) with IsoTp(arb_id_request=arb_id_request, arb_id_response=arb_id_response) as tp: # Setup filter for incoming messages tp.set_filter_single_arbitration_id(arb_id_response) with Iso14229_1(tp) as uds: # Set timeout if timeout is not None: uds.P3_CLIENT = timeout response = uds.security_access_send_key(level=level, key=key) return response
def ecu_reset(arb_id_request, arb_id_response, reset_type, timeout): """Sends an ECU Reset message to 'arb_id_request'. Returns the first response received from 'arb_id_response' within 'timeout' seconds or None otherwise. :param arb_id_request: arbitration ID for requests :param arb_id_response: arbitration ID for responses :param reset_type: value corresponding to a reset type :param timeout: seconds to wait for response before timeout, or None for default UDS timeout :type arb_id_request: int :type arb_id_response int :type reset_type: int :type timeout: float or None :return: list of response byte values on success, None otherwise :rtype [int] or None """ # Sanity checks if not BYTE_MIN <= reset_type <= BYTE_MAX: raise ValueError("reset type must be within interval 0x{0:02x}-0x{1:02x}".format(BYTE_MIN, BYTE_MAX)) if isinstance(timeout, float) and timeout < 0.0: raise ValueError("timeout value ({0}) cannot be negative".format(timeout)) with IsoTp(arb_id_request=arb_id_request, arb_id_response=arb_id_response) as tp: # Setup filter for incoming messages tp.set_filter_single_arbitration_id(arb_id_response) with Iso14229_1(tp) as uds: # Set timeout if timeout is not None: uds.P3_CLIENT = timeout response = uds.ecu_reset(reset_type=reset_type) return response
def test_security_access_request_seed_send_key_success(self): level_seed = 0x01 data_record = [] timeout = None expected_response_id = Iso14229_1.get_service_response_id(Services.SecurityAccess.service_id) # Request seed seed_result = uds.request_seed(arb_id_request=self.ARB_ID_REQUEST, arb_id_response=self.ARB_ID_RESPONSE, level=level_seed, data_record=data_record, timeout=timeout) expected_seed = self.ecu.SECURITY_ACCESS_SEED expected_seed_result = [expected_response_id, level_seed] + expected_seed self.assertListEqual(seed_result, expected_seed_result, "Security Access: Request seed gave '{0}', expected '{1}'".format( seed_result, expected_seed_result)) # Send key level_key = uds.Services.SecurityAccess.RequestSeedOrSendKey().get_send_key_for_request_seed(level_seed) key = self.ecu.SECURITY_ACCESS_KEY key_result = uds.send_key(arb_id_request=self.ARB_ID_REQUEST, arb_id_response=self.ARB_ID_RESPONSE, level=level_key, key=key, timeout=timeout) expected_key_result = [expected_response_id, level_key] self.assertListEqual(key_result, expected_key_result, "Security Access: Send key gave '{0}', expected '{1}'".format( key_result, expected_key_result))
def extended_session(arb_id_request, arb_id_response, session_type): with IsoTp(arb_id_request=arb_id_request, arb_id_response=arb_id_response) as tp: # Setup filter for incoming messages tp.set_filter_single_arbitration_id(arb_id_response) with Iso14229_1(tp) as uds: response = uds.diagnostic_session_control(session_type) return response
def test_ecu_reset_hard_reset_success(self): # ECU Reset arguments reset_type = Services.EcuReset.ResetType.HARD_RESET timeout = None # Perform ECU Reset result = uds.ecu_reset(arb_id_request=self.ARB_ID_REQUEST, arb_id_response=self.ARB_ID_RESPONSE, reset_type=reset_type, timeout=timeout) # Expected response format for successful request expected_response_id = Iso14229_1.get_service_response_id(Services.EcuReset.service_id) expected_result = [expected_response_id, reset_type] self.assertListEqual(result, expected_result, "ECU Reset gave '{0}', expected '{1}'".format( result, expected_result))
def __uds_discovery_wrapper(args): """Wrapper used to initiate a UDS discovery scan""" min_id = args.min max_id = args.max blacklist = args.blacklist auto_blacklist_duration = args.autoblacklist delay = args.delay verify = not args.skipverify print_results = True try: arb_id_pairs = uds_discovery(min_id, max_id, blacklist, auto_blacklist_duration, delay, verify, print_results) if len(arb_id_pairs) == 0: # No UDS discovered print("\nDiagnostics service could not be found.") else: # Print result table print("\nIdentified diagnostics:\n") table_line = "+------------+------------+" print(table_line) print("| CLIENT ID | SERVER ID |") print(table_line) for (client_id, server_id) in arb_id_pairs: print("| 0x{0:08x} | 0x{1:08x} |".format(client_id, server_id)) with IsoTp(arb_id_request=client_id, arb_id_response=server_id) as tp: # Setup filter for incoming messages tp.set_filter_single_arbitration_id(server_id) with Iso14229_1(tp) as uds: resp = uds.clear_all_dtcs() print(resp) print(table_line) except ValueError as e: print("Discovery failed: {0}".format(e))