MEMS3 Seed To Key Algorithm

 

The notes below show how the Pascal function which implements the Security Access seed to key algorithm in MEMS3 Mapper may be derived from the raw ECU assembly language implementation. I have shown the final Pascal implementation, a Pascal pseudocode version and the raw ECU assembly language from both firmware ksr3p004 and boot loader bootp033. The pseudocode implementation is a “half way house”, where the assembly language has been distilled down into higher level code structures but is still laid out in the order of the assembly language code with corresponding addresses.

 

Seed To Key Algorithm – Final Pascal Implementation

 

This is the final Delphi Pascal implementation of the SeedToKey method. This Pascal code is distilled from the ECU pseudocode implementation below.

 

class function TStandardMems3.SeedToKey(ASeed: Word): Word;

var

  I: Integer;

begin

  Result:=0;

  I:=1;

  if Odd(ASeed shr 15) then

    Inc(I, 8);

  if Odd(ASeed shr 7) then

    Inc(I, 4);

  if Odd(ASeed shr 4) then

    Inc(I, 2);

  if Odd(ASeed) then

    Inc(I);

  for I:=1 To I do

    begin

      Result:=(((ASeed shr 1) and $FFFE)

       or Ord(not(Odd(ASeed shr 13) and Odd(ASeed shr 3))))

       and $7FFF;

      if Odd(ASeed shr 9) xor Odd(ASeed shr 8) xor Odd(ASeed shr 2) xor Odd(ASeed shr 1) then

        Result:=Result or $8000;

      ASeed:=Result;

    end;

end;

 

Seed To Key Algorithm – Arduino C++ Implementation

 

This is the final Arduino C++ implementation of the SeedToKey method. This Arduino code is translated from the Delphi Pascal implementation above.

 

uint16_t seedToKey(uint16_t seed) {

 

  uint16_t result = 0;

  uint16_t count = 1;

 

  if (getBit(seed, 15)) {

    count += 8;

  }

  if (getBit(seed, 7)) {

    count += 4;

  }

  if (getBit(seed, 4)) {

    count += 2;

  }

  if (getBit(seed, 0)) {

    count ++;

  }

 

  for (uint16_t i = 0; i < count; i++) {

      result = (((seed >> 1) & 0xFFFE) | (getBit(seed, 13) && getBit(seed, 3) ? 0 : 1)) & 0x7FFF;

      if (getBit(seed, 9) ^ getBit(seed, 8) ^ getBit(seed, 2) ^ getBit(seed, 1)) {

        result |= 0x8000;

      }

      seed = result;

  }

 

  return result;

 

}

 

Seed To Key Algorithm – Pascal Pseudocode Implementation – Firmware ksr3p004

 

This is a pseudocode translation of the seed to key algorithm in the ECU, which is distilled from the raw assembly language implementation below. Addresses shown are for firmware version ksr3p004. In the ECU, the seed key algorithm is called as part of a process that generates a new seed then calculates the key that goes with it. The seed and key are therefore both calculated at the same time as a pair and both stored. The seed is used to generate the new seed on the next call, the key is used to compare with the value returned over OBDII. This routine is entered with the newly generated seed in register D5. It therefore starts by storing the new seed from D5 in Word variable SEED_00000bf0, which it then later references to set D6. D6 holds the key which corresponds to the seed on completion.

                            

        0012220A SEED_00000bf0:=D5;

        ... // Omitted some checking and updating of flags which is not directly relevant here.

        00122234 D1:=0;

        00122236 if Odd(D5 shr 15) then

        0012223e   Inc(D1, 8);

        00122242 if Odd(D5 shr 7) then

        0012224a   Inc(D1, 4);

        0012224e if Odd(D shr 4) then

        00122256   Inc(D1, 2);

        0012225a if Odd(D5) then

        00122262   Inc(D1);

        00122266 Inc(D1);

        0012226a D6:=SEED_00000bf0;

        0012226e for D2:=1

        00122272   to D1 do

                   begin

        00122280     D3:=0;

        00122282     if Odd(D6 shr 1) then

        0012228a       Inc(D3);

        0012228e     if Odd(D6 shr 2) then

        00122296       Inc(D3);

        0012229a     if Odd(D6 shr 8) then

        001222a2       Inc(D3);

        001222a6     if Odd(D6 shr 9) then

        001222ae       Inc(D3);

        001222b2     D4:=1;

        001222b6     if Odd(D6 shr 3)

        001222be       and Odd(D6 shr 13) then

        001222c6       D4:=0; // Equivalent to D4:=not(Odd(D6 shr 13) and Odd(D6 shr 3)).

        001222c8     D6:=D6 shr 1;

        001222ca     if (D3=1) // D3 will be 1 or 3 if an odd number of the conditions highlighted are met. This is therefore equivalent to XORing the conditions.

        001222d0       or (D3=3) then

        001222d6       D6:=D6 or $8000;

        001222da     if D4<>0 then

        001222e0       D6:=D6 or $1

        001222e4     else

        001222e6       D6:=D6 and $7FFF;

        001222ea   end;

 

 Seed To Key Algorithm – Raw ECU Assembly Implementation – Firmware ksr3p004

 

This is the raw listing of the seed to key algorithm as actually implemented in the ECU, in the firmware. Again, addresses shown are for firmware version ksr3p004.

 

                             LAB_0012220a                                    XREF[1]:     00122204 (j)  

        0012220a 31  c5  0b  f0    move.w     D5w ,(BYTE_00000bf0 ).w

        0012220e 31  fc  00       move.w     #0xfb ,(BYTE_00000514 ).w

                 fb  05  14

        00122214 31  f8  0b       move.w     (BYTE_00000bf0 ).w,(BYTE_00000516 ).w

                 f0  05  16

        0012221a 08  f8  00       bset.b     0x7 ,(byteBitFlags08F9 ).w

                 07  08  f9

        00122220 08  38  00       btst.b     0x5 ,(byteBitFlags131A ).w

                 05  13  1a

        00122226 66  0c           bne.b      LAB_00122234

        00122228 08  38  00       btst.b     0x0 ,(BYTE_00001313 ).w

                 00  13  13

        0012222e 67  ff  00       beq.l:     LAB_001222f6

                 00  00  c6

                             LAB_00122234                                    XREF[1]:     00122226 (j)  

        00122234 42  41           clr.w      D1w

        00122236 08  05  00  0f    btst.l     0xf ,D5

        0012223a 67  00  00  06    beq.w      LAB_00122242

        0012223e 06  41  00  08    addi.w     #0x8 ,D1w

                             LAB_00122242                                    XREF[1]:     0012223a (j)  

        00122242 08  05  00  07    btst.l     0x7 ,D5

        00122246 67  00  00  06    beq.w      LAB_0012224e

        0012224a 06  41  00  04    addi.w     #0x4 ,D1w

                             LAB_0012224e                                    XREF[1]:     00122246 (j)  

        0012224e 08  05  00  04    btst.l     0x4 ,D5

        00122252 67  00  00  06    beq.w      LAB_0012225a

        00122256 06  41  00  02    addi.w     #0x2 ,D1w

                             LAB_0012225a                                    XREF[1]:     00122252 (j)  

        0012225a 08  05  00  00    btst.l     0x0 ,D5

        0012225e 67  00  00  06    beq.w      LAB_00122266

        00122262 06  41  00  01    addi.w     #0x1 ,D1w

                             LAB_00122266                                    XREF[1]:     0012225e (j)  

        00122266 06  41  00  01    addi.w     #0x1 ,D1w

        0012226a 3c  38  0b  f0    move.w     (BYTE_00000bf0 ).w,D6w

        0012226e 34  3c  00  01    move.w     #0x1 ,D2w

        00122272 60  04           bra.b      LAB_00122278

                             LAB_00122274                                    XREF[1]:     001222ea (j)  

        00122274 06  42  00  01    addi.w     #0x1 ,D2w

                             LAB_00122278                                    XREF[1]:     00122272 (j)  

        00122278 b4  41           cmp.w      D1w ,D2w

        0012227a 6e  ff  00       bgt.l:     LAB_001222ec

                 00  00  70

        00122280 42  43           clr.w      D3w

        00122282 08  06  00  01    btst.l     0x1 ,D6

        00122286 67  00  00  06    beq.w      LAB_0012228e

        0012228a 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_0012228e                                    XREF[1]:     00122286 (j)  

        0012228e 08  06  00  02    btst.l     0x2 ,D6

        00122292 67  00  00  06    beq.w      LAB_0012229a

        00122296 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_0012229a                                    XREF[1]:     00122292 (j)  

        0012229a 08  06  00  08    btst.l     0x8 ,D6

        0012229e 67  00  00  06    beq.w      LAB_001222a6

        001222a2 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_001222a6                                    XREF[1]:     0012229e (j)  

        001222a6 08  06  00  09    btst.l     0x9 ,D6

        001222aa 67  00  00  06    beq.w      LAB_001222b2

        001222ae 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_001222b2                                    XREF[1]:     001222aa (j)  

        001222b2 38  3c  00  01    move.w     #0x1 ,D4w

        001222b6 08  06  00  03    btst.l     0x3 ,D6

        001222ba 67  00  00  0c    beq.w      LAB_001222c8

        001222be 08  06  00  0d    btst.l     0xd ,D6

        001222c2 67  00  00  04    beq.w      LAB_001222c8

        001222c6 42  44           clr.w      D4w

                             LAB_001222c8                                    XREF[2]:     001222ba (j) , 001222c2 (j)  

        001222c8 e2  4e           lsr.w      #0x1 ,D6w

        001222ca 0c  43  00  01    cmpi.w     #0x1 ,D3w

        001222ce 67  06           beq.b      LAB_001222d6

        001222d0 0c  43  00  03    cmpi.w     #0x3 ,D3w

        001222d4 66  04           bne.b      LAB_001222da

                             LAB_001222d6                                    XREF[1]:     001222ce (j)  

        001222d6 08  c6  00  0f    bset.l     0xf ,D6

                             LAB_001222da                                    XREF[1]:     001222d4 (j)  

        001222da 0c  44  00  00    cmpi.w     #0x0 ,D4w

        001222de 67  06           beq.b      LAB_001222e6

        001222e0 08  c6  00  00    bset.l     0x0 ,D6

        001222e4 60  04           bra.b      LAB_001222ea

                             LAB_001222e6                                    XREF[1]:     001222de (j)  

        001222e6 08  86  00  00    bclr.l     0x0 ,D6

                             LAB_001222ea                                    XREF[1]:     001222e4 (j)  

        001222ea 60  88           bra.b      LAB_00122274

 

 

 Seed To Key Algorithm – Raw ECU Assembly Implementation – Boot Loader bootp033

 

This is the raw listing of the seed to key algorithm as actually implemented in the ECU, in the boot loader. Addresses shown are for boot loader version bootp033. It is functionally identical to the routine in the firmware. It is repeated because both the firmware (General Diagnostic Session) and boot loader (Programming Diagnostic Session) support KWP2000 Service $27 “Security Access” and run independently.

 

                             LAB_00106258                                    XREF[1]:     00106252 (j)  

        00106258 31  c5  04  36    move.w     D5w ,(BYTE_00000436 ).w

        0010625c 31  fc  00       move.w     #0xfb ,(BYTE_00000294 ).w

                 fb  02  94

        00106262 31  f8  04       move.w     (BYTE_00000436 ).w,(BYTE_00000296 ).w

                 36  02  96

        00106268 08  f8  00       bset.b     0x7 ,(BYTE_00000413 ).w

                 07  04  13

        0010626e 08  38  00       btst.b     0x3 ,(BYTE_00000583 ).w

                 03  05  83

        00106274 66  0c           bne.b      LAB_00106282

        00106276 08  38  00       btst.b     0x6 ,(BYTE_0000057e ).w

                 06  05  7e

        0010627c 67  ff  00       beq.l:     LAB_00106344

                 00  00  c6

                             LAB_00106282                                    XREF[1]:     00106274 (j)  

        00106282 42  41           clr.w      D1w

        00106284 08  05  00  0f    btst.l     0xf ,D5

        00106288 67  00  00  06    beq.w      LAB_00106290

        0010628c 06  41  00  08    addi.w     #0x8 ,D1w

                             LAB_00106290                                    XREF[1]:     00106288 (j)  

        00106290 08  05  00  07    btst.l     0x7 ,D5

        00106294 67  00  00  06    beq.w      LAB_0010629c

        00106298 06  41  00  04    addi.w     #0x4 ,D1w

                             LAB_0010629c                                    XREF[1]:     00106294 (j)  

        0010629c 08  05  00  04    btst.l     0x4 ,D5

        001062a0 67  00  00  06    beq.w      LAB_001062a8

        001062a4 06  41  00  02    addi.w     #0x2 ,D1w

                             LAB_001062a8                                    XREF[1]:     001062a0 (j)  

        001062a8 08  05  00  00    btst.l     0x0 ,D5

        001062ac 67  00  00  06    beq.w      LAB_001062b4

        001062b0 06  41  00  01    addi.w     #0x1 ,D1w

                             LAB_001062b4                                    XREF[1]:     001062ac (j)  

        001062b4 06  41  00  01    addi.w     #0x1 ,D1w

        001062b8 3c  38  04  36    move.w     (BYTE_00000436 ).w,D6w

        001062bc 34  3c  00  01    move.w     #0x1 ,D2w

        001062c0 60  04           bra.b      LAB_001062c6

                             LAB_001062c2                                    XREF[1]:     00106338 (j)  

        001062c2 06  42  00  01    addi.w     #0x1 ,D2w

                             LAB_001062c6                                    XREF[1]:     001062c0 (j)  

        001062c6 b4  41           cmp.w      D1w ,D2w

        001062c8 6e  ff  00       bgt.l:     LAB_0010633a

                 00  00  70

        001062ce 42  43           clr.w      D3w

        001062d0 08  06  00  01    btst.l     0x1 ,D6

        001062d4 67  00  00  06    beq.w      LAB_001062dc

        001062d8 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_001062dc                                    XREF[1]:     001062d4 (j)  

        001062dc 08  06  00  02    btst.l     0x2 ,D6

        001062e0 67  00  00  06    beq.w      LAB_001062e8

        001062e4 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_001062e8                                    XREF[1]:     001062e0 (j)  

        001062e8 08  06  00  08    btst.l     0x8 ,D6

        001062ec 67  00  00  06    beq.w      LAB_001062f4

        001062f0 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_001062f4                                    XREF[1]:     001062ec (j)  

        001062f4 08  06  00  09    btst.l     0x9 ,D6

        001062f8 67  00  00  06    beq.w      LAB_00106300

        001062fc 06  43  00  01    addi.w     #0x1 ,D3w

                             LAB_00106300                                    XREF[1]:     001062f8 (j)  

        00106300 38  3c  00  01    move.w     #0x1 ,D4w

        00106304 08  06  00  03    btst.l     0x3 ,D6

        00106308 67  00  00  0c    beq.w      LAB_00106316

        0010630c 08  06  00  0d    btst.l     0xd ,D6

        00106310 67  00  00  04    beq.w      LAB_00106316

        00106314 42  44           clr.w      D4w

                             LAB_00106316                                    XREF[2]:     00106308 (j) , 00106310 (j)  

        00106316 e2  4e           lsr.w      #0x1 ,D6w

        00106318 0c  43  00  01    cmpi.w     #0x1 ,D3w

        0010631c 67  06           beq.b      LAB_00106324

        0010631e 0c  43  00  03    cmpi.w     #0x3 ,D3w

        00106322 66  04           bne.b      LAB_00106328

                             LAB_00106324                                    XREF[1]:     0010631c (j)  

        00106324 08  c6  00  0f    bset.l     0xf ,D6

                             LAB_00106328                                    XREF[1]:     00106322 (j)  

        00106328 0c  44  00  00    cmpi.w     #0x0 ,D4w

        0010632c 67  06           beq.b      LAB_00106334

        0010632e 08  c6  00  00    bset.l     0x0 ,D6

        00106332 60  04           bra.b      LAB_00106338

                             LAB_00106334                                    XREF[1]:     0010632c (j)  

        00106334 08  86  00  00    bclr.l     0x0 ,D6

                             LAB_00106338                                    XREF[1]:     00106332 (j)  

        00106338 60  88           bra.b      LAB_001062c2