示例#1
0
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))
示例#2
0
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)
示例#3
0
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
示例#4
0
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
示例#5
0
 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))
示例#6
0
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
示例#7
0
 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))
示例#8
0
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))