Pages: [1]
Author Topic: SID310 EEPROM CRC calculation  (Read 5327 times)
hayk57
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 4


« on: March 29, 2022, 01:21:22 AM »

Hi guys,

I am working on EEPROM CRC calculation for SID310 ECUs.

What I have found so far:



Blue: Data
Red: CKS1
Grey: Block size (number of bytes divided by 8 )
Yellow: Block ID
Purple: CKS2

The same data for different locations has different checksum:

For example block on 0xB0 and 0xC0

I tried CRC32, CRC16 ... using different poly and initial values but didn't manage to get the right checksum.

Does anyone have a hint for this checksum calculation.

Thanks


« Last Edit: March 29, 2022, 01:23:12 AM by hayk57 » Logged
d3irb
Full Member
***

Karma: +134/-1
Offline Offline

Posts: 195


« Reply #1 on: March 29, 2022, 10:04:55 AM »

This looks like most Continental DFlash CRC. There is a derived/secret piece of data (nonce) encoded into the CRC, so you will have big issues with straight CRC reversal.

Do you have the bytes FF FE in your DFlash dump? This is the record value which identifies the CRC nonce. The last two bytes will be the nonce. For example, 00010080 00000A45 0BE5F001 FFFE41A0 (record ID FF FE, CRC 41 A0, shifted CRC BE 5F, data 00010080 00000A45) means the nonce for this DFlash is 0A 45.

I figured this out by making a simple ASW patch hooking the CRC functions in flash, and writing a logger which would send me the parameters to a hooked function, in this case what is being CRCed. I intend to eventually do a write up about this strategy as it is very useful for learning things.

The bytes you have outlined in RED are the bytes in PURPLE xor FFFF << 4.

For example, 86 03 XOR FFFF -> 79 FC << 4 -> 07 9F C0.

The bytes in PURPLE are calculated like so:

CRC16_INIT_A55A_POLY_8005(DATA + INFO)

INFO is always 8 bytes: XX XX 00 00 YY YY 46 ZZ

XX XX is the NONCE.

YY YY is the LENGTH.

ZZ is the channel ID.

So for example for your channel 5 (05 46, Len 01):

15 2F 00 00 00 00 00 00 XX XX 00 00 01 00 46 05

Or split up:

15 2F 00 00 00 00 00 00 << DATA, 8 Bytes

XX XX << NONCE, recover it from FF FE record

00 00 << fixed

01 00 << len

46 05 << Channel 5

Depending on the record_way (type) of the record in ASW, it may also have an additional prefix CRC which is part of the data also. This prefix CRC is the same polynomial but init value 0xABCD.

There are a few other oddities I never quite figured out. Some records have a single byte skipped in various places in the CRC calculation and others don't.
Logged
d3irb
Full Member
***

Karma: +134/-1
Offline Offline

Posts: 195


« Reply #2 on: March 29, 2022, 10:32:51 AM »

After looking at your DFlash dump (didn't see you'd posted it) it looks like the CRC polynomial is more likely to be 1021 (CCITT instead of standard) and the nonce is B310.



Logged
hayk57
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 4


« Reply #3 on: March 29, 2022, 11:32:15 AM »

Thanks for your help,

The purple was pretty obvious.  Lips sealed

If I follow the logic you explained

I tried to find the FF FE bytes (I have it multiple time but I suppose that the interessting one are at the end) offset 0x2FE00 and 0x2FF00 with the same exact value

0001007A 00000B30 08166001 FFFE7E99

(record ID FF FE, CRC 7E 99, shifted CRC 81 66, data 0001007A 00000B30) means the nonce for this DFlash is 0B 30 ? how did you find B3 10 ?



So if I try to calculate CRC16 CCITT with 1021 poly and FFFF init on

15 2F 00 00 00 00 00 00 B3 10 00 00 01 00 46 06 (if B3 10 is considered as the nonce)

15 2F 00 00 00 00 00 00 0B 30 00 00 01 00 46 06 (if 0B 30 is considered as the nonce)

I still don't have B6 B3 as a result

I also put PFlash here if there is anything to check inside; I saw that you shared the Ghidra TC1791 preset but I haven't had time to play with it. I'm more familiar with this type of reverse than with the assembly.

Thanks again
Logged
d3irb
Full Member
***

Karma: +134/-1
Offline Offline

Posts: 195


« Reply #4 on: March 29, 2022, 12:57:18 PM »

Sorry, I just typoed the nonce, I think.

Quote
./reveng -w 16 -q 0 -s 152F0000000000000B300000010046065808 152F0000000000000B30000001004608B9C6 152F0000000000000B300000010046074829 152F0000000000000B3000000100460A9984
width=16  poly=0x1021  init=0x50e3  refin=false  refout=false  xorout=0x0000  check=0x85a8  residue=0x0000  name=(none)

This is quite promising that the polynomial really is 1021. The init may or may not be correct, I can look in the disassembly in a bit and see what it is actually doing now that you posted it, thanks!
Logged
hayk57
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 4


« Reply #5 on: March 30, 2022, 06:35:49 AM »

I think it is ok for poly 1021

So I found out that there are 2 nonces one for dflash0 and one for dflash1 (the file I put in first post is dflash0 + dflash1 combined)

0B31 for dflash0 and 0B30 for dflash1 (have to check if it is always -1 on other SID310 )

I managed to calculate CRC for some parts using reveng giving some blocks to get the initial value.

Code:
./reveng -w 16 -q 0 -s 152F0000000000000B310000010046065808 152F0000000000000B310000010046074829 152F0000000000000B31000001004608B9C6 152F0000000000000B31000001004609A9E7 152F0000000000000B3100000100460A9984 152F0000000000000B3100000100460FC921 152F0000000000000B310000010046102AFF 152F0000000000000B310000010046113ADE 

width=16  poly=0x1021  init=0x8b35  refin=false  refout=false  xorout=0x0000  check=0x84a8  residue=0x0000  name=(none)

Just need to figure out how the initial value is changing for other blocks

It seems like if the block length is 01 then init=0x8b35

I choose random 01 size blocks in file and init is always 0x8b35
« Last Edit: March 30, 2022, 07:56:06 AM by hayk57 » Logged
hayk57
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 4


« Reply #6 on: March 30, 2022, 08:03:53 AM »

Code:
./reveng -w 16 -q 0 -s 000000000000000000000000000000000B31000002004698ED19 522C0F0F0F0F000000000000000000000B3100000200460EDB79 000000000000000000000000000000000B3100000200462E2A04

width=16  poly=0x1021  init=0xb3f7  refin=false  refout=false  xorout=0x0000  check=0xdda2  residue=0x0000  name=(none)


./reveng -w 16 -q 0 -s 0000000000000000000000000001000000000000000000000B3100000300465EE2FE 57FC9D004DFC9D004DFC9D0027012901E70200FA000000000B3100000300466BD47D F3959F000000000000000000000009D600000000000000000B3100000300466CFC77 7D000000EF0000007D000000EF00000001000000000000000B3100000300466F79AE

width=16  poly=0x1021  init=0x710f  refin=false  refout=false  xorout=0x0000  check=0xa8f9  residue=0x0000  name=(none)

For block with 02 length the init=0xb3f7
For block with 03 length the init=0x710f

So for 01 length init=0x8b35
for 02 length init=0xb3f7
for 03 length init=0x710f

I don't get the logic behind this values, maybe they are stored in an array? and calulation is done using the init value based on the length
« Last Edit: March 30, 2022, 08:32:16 AM by hayk57 » Logged
d3irb
Full Member
***

Karma: +134/-1
Offline Offline

Posts: 195


« Reply #7 on: March 30, 2022, 09:43:07 AM »

I think the init value is actually be the same but there is a seemingly random byte skipped in the middle of the longer values which is throwing things off and causing crc reveng to infer a different init value. I never quite figured this part out, I just used the recorded values for the channels I cared about.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Page created in 0.016 seconds with 17 queries. (Pretty URLs adds 0s, 0q)