Skip to content

Commit

Permalink
Add experimental Subaru ROM ID based FW fingerprinting support
Browse files Browse the repository at this point in the history
  • Loading branch information
martinl committed Apr 6, 2020
1 parent cc6358d commit 7048eff
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
54 changes: 54 additions & 0 deletions panda/examples/query_fw_ssm4_subaru.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import time
import struct
from panda import Panda
from hexdump import hexdump
from panda.python.isotp import isotp_send, isotp_recv

if __name__ == "__main__":
panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327)
# 0 - white/grey panda in OBD2, 1 - black panda/comma two + CPv2 in OBD2
bus = 1
panda.can_clear(bus)

# OBD Mode 22 PIDs for Subaru
# 22 F1 00 SSM ID
# 22 F1 82 ROM ID
# 22 F1 89 Version string - only 5 non-essential ecus
# 22 F1 8E Product code
# 22 F1 90 VIN - only 7e0
# 22 F1 97 System String

# ECU TX addresses for Crosstrek 2018 discovered by selfdrive/car/fw_versions.py --scan
ecu_list = [0x735, 0x746, 0x747, 0x752, 0x753, 0x780, 0x783, 0x787, 0x7b0, 0x7c4, 0x7d0, 0x7e0, 0x7e1, 0x7f1]
# 0x756 responds in accessory mode only
#ecu_list = [0x756]

cmd_list = [0x00, 0x82, 0x89, 0x8e, 0x90, 0x97]

# Query all proprietary UDS DID ranges
# identificationOptionVehicleManufacturerSpecific (22 F1 00 - 7F)
#cmd_list = []
#for i in range(128):
# cmd_list.append(i)

# identificationOptionSystemSupplierSpecific (22 F1 F0 - FF)
#cmd_list = []
#for i in range(240, 256):
# cmd_list.append(i)

cnt = 1

for n in cmd_list:
for tx_addr in ecu_list:
rx_addr = tx_addr + 8
cmd = b'\x22\xf1' + n.to_bytes(1, byteorder='big')

print("%d" % cnt)
print('0x%x ' % tx_addr + ''.join(r'\x{:02x}'.format(x) for x in cmd))
isotp_send(panda, cmd, tx_addr, bus)
ret = isotp_recv(panda, rx_addr, bus)
hexdump(ret)
print("0x%x %s" % (rx_addr, "".join(map(chr, ret[3:]))))
cnt += 1
17 changes: 15 additions & 2 deletions selfdrive/car/fw_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from cereal import car
Ecu = car.CarParams.Ecu

# 0 - white/grey panda connected to OBD2
# 1 - black panda/comma two + CPv2 connected to OBD2
bus = 1

def p16(val):
return struct.pack("!H", val)

Expand Down Expand Up @@ -42,6 +46,10 @@ def p16(val):
OBD_VERSION_REQUEST = b'\x09\x04'
OBD_VERSION_RESPONSE = b'\x49\x04'

SUBARU_VERSION_REQUEST= b'\x22\xf1\x82'
SUBARU_VERSION_RESPONSE= b'\x62\xf1\x82'



REQUESTS = [
# Honda
Expand All @@ -61,6 +69,11 @@ def p16(val):
(
[TESTER_PRESENT_REQUEST, DEFAULT_DIAGNOSTIC_REQUEST, EXTENDED_DIAGNOSTIC_REQUEST, UDS_VERSION_REQUEST],
[TESTER_PRESENT_RESPONSE, DEFAULT_DIAGNOSTIC_RESPONSE, EXTENDED_DIAGNOSTIC_RESPONSE, UDS_VERSION_RESPONSE]
),
# Subaru
(
[SUBARU_VERSION_REQUEST],
[SUBARU_VERSION_RESPONSE]
)
]

Expand Down Expand Up @@ -186,13 +199,13 @@ def get_fw_versions(logcan, sendcan, bus, extra=None, timeout=0.1, debug=False,

t = time.time()
print("Getting vin...")
addr, vin = get_vin(logcan, sendcan, 1, retry=10, debug=args.debug)
addr, vin = get_vin(logcan, sendcan, bus, retry=10, debug=args.debug)
print(f"VIN: {vin}")
print("Getting VIN took %.3f s" % (time.time() - t))
print()

t = time.time()
fw_vers = get_fw_versions(logcan, sendcan, 1, extra=extra, debug=args.debug, progress=True)
fw_vers = get_fw_versions(logcan, sendcan, bus, extra=extra, debug=args.debug, progress=True)
candidates = match_fw_to_car(fw_vers)

print()
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/car/isotp_parallel_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(self, sendcan, logcan, bus, addrs, request, response, functional_ad

def rx(self):
"""Drain can socket and sort messages into buffers based on address"""
can_packets = messaging.drain_sock(self.logcan, wait_for_one=True)
can_packets = messaging.drain_sock(self.logcan, wait_for_one=False)

for packet in can_packets:
for msg in packet.can:
Expand Down
13 changes: 13 additions & 0 deletions selfdrive/car/subaru/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ class CAR:
}],
}

FW_VERSIONS = {
CAR.IMPREZA: {
# Ecu, addr, subaddr: ROM ID
(Ecu.esp, 0x7b0, None): [b'\x7a\x94\x3f\x90\x00'],
(Ecu.eps, 0x746, None): [b'\x7a\xc0\x0c\x00'],
(Ecu.srs, 0x780, None): [b'\x00\x92\x15\x16\x00'],
(Ecu.fwdCamera, 0x787, None): [b'\x00\x00\x64\xb5\x1f\x40\x20\x0e'],
(Ecu.engine, 0x7e0, None): [b'\xaa\x61\x66\x73\x07'],
(Ecu.transmission, 0x7e1, None): [b'\xe3\xe5\x46\x31\x00'],
},
}


STEER_THRESHOLD = {
CAR.IMPREZA: 80,
}
Expand Down

0 comments on commit 7048eff

Please sign in to comment.