Seca algo

K

Kcplus

Wie weet er meer over het seca algorithme?

Goed, de vraag blijft hoe lang we er nog iets aan hebben, maar het leek mij toch leuk te weten hoe het in elkaar steekt.

Dus eindelijk ruim twee jaar na het downloaden heb ik mij er maar aan gewaagd:

ik ben de Media1.doc van John MacDonald (Mediaguard Musings) gaan bestuderen. Ook de excel-sheet "Seca.xls", welke op het www te vinden is, heb ik uitgeplozen.

Hoewel ik denk de in de .xls uitgewerkte algo te begrijpen en daadwerkelijk meen dat de daarin neergezette algo overeenkomt met de .doc kom ik niet op de gewenste resultaten.

Een CW decrypten leidt nimmer tot het resultaat dat die mooie proggies als MKF voor mij berekenen.

Is er iemand, die e.e.a. al eerder bestudeerd heeft en wel tot resultaat is gekomen, die mij op weg wil helpen?

Of wil iemand samen met mij deze slag aan?

 
De posting wordt wel gelezen......

dus:

- of het onderwerp is niet interessant :confused: ;

- of ik ben de enige sathobbyist die het algo nog steeds niet kent :rolleyes: ;

- of we hebben het allemaal te "druk" met andere zaken :biggrin: ;

- of de echte cracks denken: "zoek het even lekker zelf uit!" :tong: ;

- of het is echt te moeilijk, dus waar ben ik aan begonnen :sad:

- of .......................... :eek:

Ik ga dus maar gewoon door, en meld mijzelf "ooit" wel met de oplossing.........

hoop ik.........

toch?

snif

 
Het probleem is dat je wel enigszins wiskundig onderlegd moet zijn voor deze materie. iets wat bij mij volledig ontbreekt dus.

Ooit ben ik er ook, niet gehinderd door enige vorm van kennis aan begonnen, maar door tijdgebrek, gebrek aan inzicht weer mee gestopt.

Of je er verder echt zo weinig aan zult hebben ?

het seca II algo zal echt niet teveel verschillen van de seca I, hoogstens zijn de hash tabellen anders.

ik kan je dan ook alleen maar succes wensen, en hopen dat je je kennis ooit nog eens kan aanwenden in een leuk programmatje voor een funkaartje ofzo :)

Peter

 
Nee, eenvoudig is het niet.

Ik heb verscheidene sources bestudeerd zowel van seca als van viaccess. Ik ben nooit verder gekomen als de locatie te vinden waar de providers in vermeld zitten met hun benaming, alsook heb ik het controle systeem kunnen uitdokteren, dit is gewoon een soort optelsom.

Ik ben spijtig genoeg geen programmeur en heb moeten afhaken. Je moet immers zéér goed assembler kennen.

 
Hoi kc+ ben je FAQ van Roland von Gilead al eens tegengekomen? vind ik de duidelijkste die er is.

als je wilt mail ik de duits/engels talige wel naar je toe.

suc6 met de hobby

 
@alexje

Of ik de faq van RvG wel eens ben tegengekomen? Man, ik ken dat ding bijna helemaal uit mijn hoofd ;) :biggrin: .

@ petertje

@ satelliet

Zoals gezegd heb ik destijds de seca.xls en de doc van John MacDonald gedownload. Toentertijd zag dat er uit als "abacadabra".

Ook ik ben wel eens een source tegengekomen van een seca.hex, maar daar begreep ik weinig tot niets van: geen enkele kennis van progammeren dus.....

Sinds ik van het secasysteem het een en ander weet (RvG-faq!) biedt een seca log of een gemiddelde -Ins nauwelijks meer geheimen.

Het werd dus tijd voor meer diepgang in de hobby.

Dus de seca.xls van stal gehaald.

Ik moet zeggen: ik heb daar inmiddels veel kennis uitgehaald met betrekking tot bits en bytes, de samenhang tussen decimale en hexadecimale notatie, de xor-bewerking en andere zaken.

De doc geeft dus inzicht in hoe de seca-algo zou moeten werken, en de xls zet de rekenkundige bewerkingen in een meer helder en praktisch daglicht. Echter: de uitkomsten stroken niet met die van de seca-proggies.

Maar wie weet doe ik hier dus iets geheel fout........

Ik ben nu bezig de algo geheel opnieuw "na te bouwen" in Quattro Pro (de spreadsheet van Corel/Wordperfect) omdat de hexadecimale bewerkingen daar n.m.m. eenvoudiger kunnen worden vormgegeven. Tot nu toe zijn de uitkomsten identiek aan die van de excel-sheet. Wie weet kom ik de "kink in de kabel" nu wel toevallig tegen.

Een andere mogelijke oplossing is een asm-file eens te vergelijken met de in de spreadsheet uitgewerkte algo. Ook hierbij moeten de verschillen in bewerkingen duidelijk kunnen worden.

Bedankt voor jullie reacties.

Ik ben blij dat ik niet de enige ben die het algorithme interessant vindt ;)

Wij zoeken verder................

 
Zou het dan toch onbegonnen werk zijn........?

Ik heb de seca.xls helemaal nagebouwd in quattropro. Helaas, alle uitkomsten zijn exact gelijk.

Het verhaal is echter wel meer "leesbaar" geworden. Alle binaire notaties heb ik vervangen door hexadecimale en dat leest ff makkelijker.

De oplossing heeft het echter niet gebracht.

Een secanix-source zou de oplossing moeten bieden, maar ik moet beamen: die assembler leest wel, maar niet makkelijk ;) .

Ik heb mij geconcentreerd op de verwerking van een Ins C1 3C.

Wat ik erg verhelderend vond (denk ik althans ;) ) was in te zien hoe de cam en de card met elkaar communiceren, en welke acties er nu precies in de eepromdata en het RAM plaatsvinden.

Het proggie Picachu (met windows voor RAM en Eedata) was mij daarbij ook behulpzaam. Deze soft emuleert (en logt) d.m.v. werkende hexfiles. Ik ben er echter nog niet achter hoe ik met dat proggie alle stappen van het decoderingsproces kan doorlopen. Ik denk dat helaas alleen de "grote" stappen daarmee zichtbaar worden.

Het grootste gedeelte van de decrypt-procedure snap ik ook, en leidt niet tot nieuwe inzichten. Laten nu net die gedeelten die gaan over de be- en verwerking van het CW gedeeltelijk onduidelijk blijven.....

Met name waar het gaat over de "swap_nibbles" heb ik niet het idee gekregen dat dat overeenstemt met de Media1.doc maar dat zal ik wel mis hebben.

Wie leest er (een beetje) assembler en wil mij helpen?

Anders blijft er voor mij niets anders over het geheel weer twee jaar te laten liggen :biggrin: .

 
PIC assembler kan ik wel aardig lezen, verder is de rekenkundige kracht van een PIC erg gering, met een beetje basic (N)AND (N)OR

XOR etc kennis kom je een heel eind.

Het enige verwarrende kan misschien zijn dat de decrypt routine uit de externe eeprom de hash table leest, en dat gebeurt via I2C

gelukkig wel byte voor byte, maar met goed meetellen kom je een heel eind...:)

Post de assembler evt. hier, dan hebben anderen er ook nog wat aan..

Grtz FranX

 
hier de secanix assem. voor de liefhebbers.

; Version 44.2G

; 2000, November 26

; Supports:

; autoupdate

; remote update

; superencription

; LED flashing on CAM comms

; LED set on keys/subscription date update

;------------------------------------------------------------------------------------

;

; PIC 16F84/16C84

; _______ _______

; | \/ |

; LED GREEN__RA2 --+ 1 << >> 18 +-- RA1__YELLOW LED

; | |

; LED GREEN2__RA3 --+ 2 >> 17 +-- RA0__RED LED

; | |

; not used__rtcc --+ 3 << 16 +-- OSC1/CLKIN__from CAM (CLOCK)

; | |

; from CAM__MCLR --+ 4 >> 15 +-- OSC2/CLKOUT__not used

; | |

; from CAM__Vss --+ 5 >> << 14 +-- Vdd__from CAM

; | |

; not used__RB0 --+ 6 <> 13 +-- RB7__from /to CAM (data)

; | |

; not used__RB1 --+ 7 << 12 +-- RB6__from CAM (CLOCK)

; | |

; not used__RB2 --+ 8 >> 11 +-- RB5__SCLK to EEprom

; | |

; not used__RB3 --+ 9 <> 10 +-- RB4__SDAta from / to EEprom

; | |

; +----------------+

;

; ">>" and "<<" indicate connected pins.

;

;------------------------------------------------------------------------------------

;

; 24C16/24LC16

; _______ _______

; | \/ |

; Gnd__A0 --+ 1 << 8 +-- VCC (2.5-5.5 24LCXX / 4.75-5.25 24CXX)

; | |

; Gnd__A1 --+ 2 << 7 +-- Write Protection__Gnd

; | |

; Gnd__A2 --+ 3 << 6 +-- SCLK__Serial Clock (max 400 Khz)

; | |

; GND --+ 4 >> <> 5 +-- SDA__Serial Data input/Output

; | |

; +----------------+

;

; Signal Condition

; SCLK ___|---|___|---|___|---|___|---|___|---|___|---|___|---|___|---|__

; SDA ====>-<=====>-<=====>-<=====>-<=====>-<=====>-<=====>-<=====>-<===

;

; Data Transfer

; S = Start Bit

; 1 = hight level logic

; 0 = low level logic

; B = Block Address

; C = Address

; D = Data

; X = dont care

; R = 1Read 0Write

; A = ACK (0 level)

; N = NO ACK (1 level)

; P = Stop Bit

;

; ---Control byte---- ---Address byte-- ---Data byte-----

; | | | | | |

; 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2

; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

; | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

; Byte Write S 1 0 1 0 B B B R A B B B B B B B B A D D D D D D D D A P

;

; ---Control byte---- ---Address byte-- ---Data byte----- ---Data byte-----

; | | | | | | | |

; 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 ---- n n n

; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ---- 1 2 3

; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ---- | | |

; Page Write S 1 0 1 0 B B B R A B B B B B B B B A D D D D D D D D A D D D D D D D D A D D D ---- D A P

; 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 15

;

; ---Control byte---- ---Data byte-----

; | | | |

; 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2

; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

; | | | | | | | | | | | | | | | | | | | |

; Byte Read S 1 0 1 0 B B B R A D D D D D D D D N P

;

; ---Control byte---- ---Address byte-- ---Control byte---- ---Data byte-----

; | | | | | | | |

; 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3

; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

; Byte Read Add S 1 0 1 0 B B B R A B B B B B B B B A S 1 0 1 0 B B B R A D D D D D D D D N P

;

; ---Control byte---- ---Data byte----- ---Data byte----- ---Data byte-----

; | | | | | | | |

; 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 ---- n n n

; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 ---- 1 2 3

; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ---- | | |

; Seque. Read S 1 0 1 0 B B B R A D D D D D D D D A D D D D D D D D A D D D D D D D D A ---- D N P

; 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 X

;

;------------------------------------------------------------------------------------

LIST P=16F84, F=INHX8M

include "P16F84.inc"

errorlevel 1,-224,-302

;******************************************************

constant LED=1 ; <===

;******************************************************

constant T_SERIAL = 0x1A ; 0x1B for Kenwood

constant T_SEND_START = 0x32

constant T_SEND_STOP = 0x4F

constant T_RECEIV_START = 0x2A

constant T_RECEIV_STOP = 0x28

; LED policy:

; Green is turned on by start of comms from/to CAM, and it is turned off by end of comms from/to CAM

; Yellow is turned on by Ins 1a and 5a, and it is turned off by Ins 3c

; Red is turned on by key and subscription updates

; Green2 is not used by now

; Yellow, Red and Green2 are turned off by entering PIN menu or by entering 0000 as PIN

IF LED

constant LED_RED = 0 ; Red LED (RA0)

constant LED_YELLOW = 1 ; Yellow LED (RA1)

constant LED_GREEN = 2 ; Green LED (RA2)

constant LED_GREEN2 = 3 ; Green2 LED (RA3)

ENDIF

;******************************************************

ORG 0x0000

CALL Std_pause ; Returns W=0

; The following is obsolete, but more compact

TRIS PORTA ; Define PORT as all output

IF LED ;

MOVWF PORTA ; Init LED ports (RA0,1,2,3)

BSF PORTA,LED_GREEN2 ;\

BSF PORTA,LED_RED ; LED check

BSF PORTA,LED_YELLOW ; start

ENDIF ;/

ADDLW 0x7F ; Load OPTION register with 0x7f (PORT B pull-ups enabled)

OPTION

; Code above should be written instead as

; BSF STATUS,RP0 ; Select bank 1

; MOVWF TRISA ; Define PORT A as all output

; IF LED ;\

; MOVWF PORTA ; Init LED ports (RA0,1)

; ENDIF ;/

; BCF OPTION_REG, NOT_RBPU ;PORT B pull-ups enabled, OPTION_REG is set to 0XFF on all resets

; BCF STATUS,RP0 ; Select bank 0

; Read the ATR bytes stored in the pic eeprom in reverse order, starting from position 0x0E down to

; position 0x01, 14 bytes total

MOVLW 0x0E ; ATR end address

MOVWF 0x10 ; Internal eeprom pointer

ATR_loop MOVF 0x10,W ;\

CALL Rd_eeprom ;

CALL Send ; ATR

DECFSZ 0x10,f ;

GOTO ATR_loop ;/

IF LED ;\

MOVWF PORTA ; \

BCF PORTA,LED_GREEN2 ; LED check

BCF PORTA,LED_RED ; stop

BCF PORTA,LED_YELLOW ; /

ENDIF ;/

; Send status bytes 9000, end of response with no error, or 900D when an error is simulated

; If bit 3 of PCLATH has value 1 then a 901D is sent, else 9000 is sent

; Status bytes 901D are sent on reception of a C1 40 command which does not contain keys

; since this reduces the message traffic between cam and card

TX9000 MOVLW 0x90

TX00_1D CALL Send

MOVLW 0x00 ; 9000

BTFSC PCLATH,0x03 ; (use of bits 3:4 of PCLATH is discouraged)

MOVLW 0x1D ; 901D

CALL Send

CLRF PCLATH ; Reset PCLATH

; Wait for and receive the first byte of the command (C1)

; THIS CALLS THE MAIN LOOP

CALL Receive ; Get class byte (SECA: C1), discard it

; Read the remaining 4 bytes from the command header and put

; them into RAM starting from RAM position 0x0C,

; that is

; 0x0C: Instruction byte

; 0x0D: P1

; 0x0E: P2

; 0x0F: Length

MOVLW 0x0C ; Initialize pointer

MOVWF FSR ; to RAM

Com_loop CALL Receive ; Read 1 byte

MOVWF INDF ; store it into RAM

MOVWF 0x10 ; store it into 0x10 also

INCF FSR,f ; Increment pointer to next RAM location

BTFSS FSR,0x04 ; is 0x1F pointed?

GOTO Com_loop ; no, repeat

; yes, the last stored value was in RAM location 0x0F

; The instruction to be processed is in RAM position 0x0C, while the list of valid

; instructions is stored in a table in the internal EEPROM starting from position 0x0E

; it contains 0x0E commands in this version

MOVLW 0x0E ; We have 0x0E instructions

MOVWF 0x11 ; instructions counter

Comm_scan MOVF 0x11,W

ADDLW 0x0E ; Offset wrt internal EEPROM

CALL Rd_eeprom ; Read an instruction

XORWF 0x0C,W

BTFSC STATUS,Z ; if this is the received instruction

GOTO Send_ack ; then jump to process it

DECFSZ 0x11,f ;\ else decrement the instructions counter

GOTO Comm_scan ;/ and look down in the instruction table

MOVLW 0x6D ; If the received instruction is not found, return 6D00

GOTO TX00_1D

Send_ack MOVF 0x0C,W ;\ ACK (echo of instruction byte in 0x0C)

CALL Send ;/

MOVF 0x11,W ; 0x11 contains the instruction index in the EEPROM table

; The following has been modified to be position independent

; ADDLW 0x2B ; (2B was the MOVVWF address, substitute to 2B the correct MOVWF address)

ADDLW Tab_instr ; Add the instruction index to the Tab_instr label address

; In the following a table is contained which corresponds to the instructions table

; stored in the internal EEPROM, i.e. in the same order

; The program counter is then set to the same offset in this table as the received instruction

; in the instruction table

Tab_instr MOVWF PCL ; Jump to the GOTO which actually processes the command

GOTO Instr_0A ; Operating system version

GOTO Instr_0E ; Serial number

GOTO Instr_16 ; Number of providers

GOTO Instr_12 ; Provider ID (ident)

GOTO Instr_34 ; Data request specification

GOTO Instr_32 ; Data request

GOTO Instr_22 ; Key update ?

GOTO Instr_30 ; PIN protected transaction

GOTO Instr_21 ; External EEPROM read ?

GOTO Instr_3A ; ECM decoding control word

GOTO Instr_3C ; ECM coding control word

GOTO Instr_40 ; EMM subscription management

GOTO Instr_1A ; Key index selection

GOTO Instr_5A ; CipherText selection

; Not supported yet:

; 3E key request

; 68 CSD attack (seems it probes ID 13,14,15)

;=======================================================================

; C1 INSTRUCTION PROCESSING

;=======================================================================

;*************************************************

; function : 5A C1 CLASS instruction *

; CipherText selection *

;*************************************************

; The (P2+1) values for instr. 5a are stored in a table in the internal EEPROM

; starting at offset 0x30 (this table is indexed by the P1 value)

; The number of bytes to be returned is contained in the register file 0x10

; (copy of 0x0F, command length parameter)

Instr_5A

IF LED ;\

BSF PORTA,LED_YELLOW ; Yellow LED on

ENDIF ;/

INCF 0x0E,f ; Increment P2 by one

MOVF 0x0D,W ; Load P1 value (0-15) in W

ADDLW 0x30 ; Add table start address to W

CALL Rd_eeprom ; Read the value indexed by P1 from the table

ANDWF 0x0E,W ;\ If ((P2+1) and (value read from 5a answer table))=0

BTFSS STATUS, Z ; then 9000 will be returned as status bytes at end of response

BSF PCLATH,0x03 ;/ else 901D

MOVLW 0xFF ;\ Transmit as many 0xFF as stored in file register 0x10

GOTO send_w_fill ;/ followed by the status bytes

;*************************************************

; function : 0E C1 CLASS instruction *

; request smartcard serial number *

; command : C1 0E 00 00 08 *

; answer : 0E 00 03 00 00 00 CA 13 66 90 00 *

; i.e. region is 03, UA is 00 00 00 CA 13 66 *

; It corresponds to serial number 013.243.238 *

;*************************************************

; Instr. 0E: send the byte sequence stored from offset 0x00 in the external EEPROM

; The number of bytes to be sent was stored in file register 0x0F (it should be :cool:

Instr_0E MOVLW 0x00 ; Offset in the external EEPROM

COMM_EEPR CALL EEPROM_send ; Transmit data from external EEPROM

GOTO TX9000 ; Transmit status bytes

;*************************************************

; function : 0A C1 CLASS instruction *

;*************************************************

; Instr. 0A: send the byte sequence stored from offset 0x1BB to offset 0x1FF in the external EEPROM

Instr_0A INCF PCLATH,f ; Offset in the external EEPROM, high byte, page 1 (i.e. set PCLATH to 1)

MOVLW 0xBB ; Offset in the external EEPROM, low byte

GOTO COMM_EEPR ; Transmit answer

;*************************************************

; function : 1A C1 CLASS instruction *

;*************************************************

; Instr. 1A: send the byte sequence stored from offset 0x1A6 to offset 0x1BA in the external EEPROM

Instr_1A

IF LED ;\

BSF PORTA,LED_YELLOW ; Yellow LED on

ENDIF ;/

INCF PCLATH,f ; Offset in the external EEPROM, high byte, page 1 (i.e. set PCLATH to 1)

MOVLW 0xA6 ; Offset in the external EEPROM, low byte

GOTO COMM_EEPR ; Transmit answer

;*************************************************

; function : 16 C1 CLASS instruction *

; ENTITIES SUPPORTED *

;*************************************************

; Instr. 16: send the byte sequence stored from offset 0x08 in the external EEPROM

Instr_16 MOVLW 0x08 ; Offset in the external EEPROM

GOTO COMM_EEPR ; Transmit answer

;*************************************************

; function : 12 C1 CLASS instruction *

; this instruction requests an ID CAM *

; command : C1 12 aa 00 18 *

; aa is the ID provider *

; answer : 12 ii ii bb bb bb bb bb bb bb bb bb *

; bb bb bb bb bb bb bb 00 xx xx xx zz *

; zz 90 00 *

; ii ii : provider channel *

; bb..bb : provider name *

; xx..xx : smartcard address (PPUA) * *

; zz zz : termination date ( 7 bits year since *

; 1990 + 4 bits month + 5 bits day ) *

;*************************************************

; Instr. 12: file register 0x0D contains P1, i.e. the provider ID

; W is initialized by -8 (0xF8) and each loop iteration increments W by 0x18 which is the

; length of the ID CAM for each provider. Since the loop starts by incrementing W, the first provider

; data (P1=0) are stored from offset 0x18-0x08=0x10 in the external EEPROM. Moreover a check is provided

; to increment PCLATH when the external EEPROM offset 0x100 has to be reached. Than at the end of the loop

; PCLATH contains the high byte for the external EEPROM address to be read and W the low byte

Instr_12 MOVLW 0xF8 ; Initialize offset in the external EEPROM to -8

INCF 0x0D,f ; P1 + 1 loop iterations, since 1st provider corresponds to P1=0

instr_12_loop

ADDLW 0x18 ; ID CAM length

BTFSC STATUS,Z ;\ If 0x100 has been reached

INCF PCLATH,f ;/ then increment PCLATH (i.e. set PCLATH to 1)

DECFSZ 0x0D,f ;\ Loop until the provider specified by P1 is reached

GOTO instr_12_loop ;/

GOTO COMM_EEPR ; Transmit answer

;*************************************************

; function : 3C C1 CLASS instruction *

; ENTITLEMENT CONTROL MESSAGE *

;*************************************************

; command :

; C1

; 3C ; command

; 04 ; 4-th provider on the card

; 0C ; key 0C

; 27 ; 27H bytes long

; answer:

; 3C ; ACK

; 71 00 ; unknown

; 00 10 ; provider

; 07 D0 ; year

; 00 08 ; month

; 27 ; separator

; 15 0C ; complete data

; 13 21 ; boundle

; [D1] ; marker

; EF 44 F8 57 15 A0 A0 A6 ; control word 1

; D0 11 1C 81 87 6E 24 8E ; control word 2

; 82 ; separator

; 23 C0 DF FB 10 19 62 DB ; signature

; 90 00 ; status bytes

;

; This instruction sends encrypted control words to be decrypted

; First GET_CW_loop is called. That routine receives the remaining part of the command,

; reads the 16 bytes key from the external EEPROM according to P1 and P2, and in case of

; superencription it implements the first decription

Instr_3C

IF LED ;\

BCF PORTA,LED_YELLOW ; Yellow LED off

ENDIF ;/

CALL GET_CW_loop ;

; The routine swap_eedat swaps an 8-bytes block with another

; W has to contain the st block starting position and EEADR the offset of the 1st block wrt the 2nd

; In 0x14 GET_CW_loop has stored the first free position following the command just received

; Swap the block starting 0x11 bytes before the last byte with the one starting at 0x0C

MOVF 0x14,W ;\

SUBLW 0x1D ; 1st block offset wrt 2nd block (0x1D is used as offset since it is 0x11+0x0C)

MOVWF EEADR ;/

MOVLW 0x0C ; First block start

CALL swap_eedat ; Swap blocks

; Load into 2nd encrypted word position

CALL swap_2C_38 ; Swap bytes 0x0C-0x13 with 0x38-0x3F

; Swap the block starting 0x19 bytes before the last byte with the one starting at 0x0C

MOVF 0x14,W ;\

SUBLW 0x25 ; 1st block offset wrt 2nd block (0x25 is used as offset since it is 0x19+0x0C)

MOVWF EEADR ;/

MOVLW 0x0C ; First block start

CALL swap_eedat ; Swap blocks

; Load into 1st encrypted word position

CALL swap_24_30 ; Swap bytes 0x0C-0x13 with 0x30-0x37

; Decrypt the two control words

CALL Decrypt ; Decrypt 1st word

CALL swap_F8_30 ; Swap 1st and 2nd word (0x30-0x37 with 0x38-0x3F)

CALL Decrypt ; Decrypt 2nd word

CALL swap_F8_30 ; Swap words again

GOTO TX9000 ; That's all, transmit status bytes

;-----------------------------------------------------------------------

GET_CW_loop MOVLW 0x31 ;\

SUBWF 0x10,W ; If the command contains at most 0x31 bytes (in 0x10 was a copy of the length parameter)

BTFSS STATUS,C ;/

GOTO store18 ; then start storing it from RAM position 0x18

MOVLW 0x08 ;\

SUBWF 0x10,f ; else decrease length by 8

MOVWF 0x0F ; and receive and discard 8 bytes

CALL Rec_skip ;/

GOTO GET_CW_loop ; Repeat until at most 0x31 bytes are left to receive

store18 MOVLW 0x18 ;\ Store the remaining part of the command

MOVWF FSR ;/ starting from RAM position 0x18 (at most 0x31 bytes)

store18_loop

CALL Receive ; Receive 1 byte

MOVWF INDF ; store it

INCF FSR,f ; Increment pointer

DECFSZ 0x10,f ;\ until the number of bytes contained in 0x10 is received

GOTO store18_loop ;/

MOVF FSR,W ;\ Save in 0x14 the pointer to the next free position

MOVWF 0x14 ;/ following the command just received

CALL kaddress ; Compute the external EEPROM address for the key to be used

; Since the maximum stored portion of a command starting from offset 0x18 is 0x31 bytes,

; then keys loaded starting from offset 0x40 can overwrite at most the last 9 bytes of the

; stored command (bytes 0x40-0x48), but they are not needed since they contain nano 0x82 (1 byte)

; followed by the signature (8 bytes)

; So 0x40 is the lowest safe RAM position for loading keys

MOVLW 0x40 ;\ Load keys into RAM starting from offset 0x40

MOVWF FSR ;/

CALL Get_key_10 ; Read 8 bytes key from external EEPROM

MOVLW 0x40 ;\ If a secundary key is used

BTFSC 0x0D,03 ; then read it from external EEPROM 0x40 bytes forward

ADDWF 0x10,f ;/ that is from the next provider

CALL Get_key_10 ; Either read secundary key or re-read the same key as above

BTFSS PCLATH,04 ;\ If no superencription

GOTO cw_return ;/ then return, else decrypt the entire command stored from 0x18

MOVLW 0x18 ;\ Swap 0x30-0x37 with 0x18-0x1F

CALL swap_xx_30 ;/

CALL Decrypt ; Decrypt

MOVLW 0x18 ;\ Swap 0x30-0x37 with 0x18-0x1F

CALL swap_xx_30 ;/

MOVLW 0x10 ;\ Swap 0x30-0x37 with 0x20-0x27

CALL swap_xx_30 ;/

CALL Decrypt ; Decrypt

MOVLW 0x10 ;\ Swap 0x30-0x37 with 0x20-0x27

CALL swap_xx_30 ;/

MOVLW 0x08 ;\ Swap 0x30-0x37 with 0x28-0x2F

CALL swap_xx_30 ;/

CALL Decrypt ; Decrypt

MOVLW 0x08 ;\ Swap 0x30-0x37 with 0x28-0x2F

CALL swap_xx_30 ;/

CALL swap_F8_30_encr; Swap 0x30-0x37 with 0x38-0x3F and decrypt

swap_F8_30_encr

CALL swap_F8_30 ; Once again

CALL Decrypt

cw_return RETURN

; Swap the block 0x30-0x37 with 0x38-0x3f

swap_F8_30 MOVLW 0xF8 ; Load -8 into W

; Swap the block 0x30-0x37 with the 8 bytes block starting at 0x30 minus W

swap_xx_30 MOVWF EEADR ; 1st 8-bytes block offset wrt 2-nd block should be loaded into EEADR

MOVLW 0x30 ; 1st 8-bytes block starting address should be loaded into W

CALL swap_eedat ; Swap the 8 bytes block starting at W with the 8 bytes block starting at W minus EEADR

RETURN

; SECA decription routine

; 0x0F points to the key element which is being processed (0x00..0x0F)

; 0c0D is the "C" constant

Decrypt CLRF 0x0F

MOVLW 0x02 ;\ Set PCLATH to 2

MOVWF PCLATH ;/ since SECA table 1 starts at offset 0x200

CLRF 0x0D

; Key preparation

keyprep_loop

CALL kbprep ; Set K=K XOR T1[K[i-1] XOR K[i+1] XOR C] (i is the value in 0x0F)


INCF 0x0F,f ; i=i+1



MOVF 0x0F,W ;\



ANDLW 0x03 ; Every 4 loop iterations the constant "C" is incremented



BTFSC STATUS,Z ;



INCF 0x0D,f ;/



BTFSS 0x0F,0x06 ;\ 64 iterations



GOTO keyprep_loop ;/


 


; Step 1: XOR key bytes with data bytes. Also set initial lookups for Step 2


 


MOVLW 0x0F ;\ Constant "C" is initially set to the value 0x0F



MOVWF 0x0D ;/



MOVLW 0x0C ;\ i=13 (13th key element)



MOVWF 0x0F ;/ so the index in 0..15 (0x00...0xFF) is 12 (0x0C)



keydata_loop



CALL kbget_0f ; Read K
and store it into W


XORWF 0x34,W ; W=d[4] XOR K



CALL Get_tab1



MOVWF 0x10 ; [0x10]=T1[d[4] XOR K
]


CALL kbget_0f_p1 ; Read K[i+1] and store it into W



XORWF 0x35,W ; W=d[5] XOR K[i+1]



CALL Get_tab1



MOVWF 0x11 ; [0x11]=T1[d[5] XOR K[i+1]]



CALL kbget_0f_p1 ; Read K[i+2] and store it into W



XORWF 0x36,W ; W=d[6] XOR K[i+2]



CALL Get_tab1



MOVWF 0x12 ; [0x12]=T1[d[6] XOR K[i+2]]



CALL kbget_0f_p1 ; Read K[i+3] and store it into W



XORWF 0x37,W ; W=d[7] XOR K[i+3]



CALL Get_tab1



MOVWF 0x13 ; [0x13]=T1[d[7] XOR K[i+3]]


 


; Step 2: core function. The step (T1 table lookup) has been performed in the previous step



; The new values for d[4]..d[7] are stored in 0x10..0x13



; At the end of Step 1 W contains d[7]


 


INCF PCLATH,f ; PCLATH=3, block address of T2 in the external EEPROM is 3 (offset 0x300)


 


XORWF 0x10,f ; d[4]=d[4] XOR d[7]



SWAPF 0x13,W ; Swap nibbles in d[7]



ADDWF 0x12,W ; W=~d[7]+d[6]



CALL Get_tab2 ; W=T2[W]



MOVWF 0x12 ; d[6]=T2[~d[7]+d[6]]



XORWF 0x13,f ; d[7]=d[7] XOR d[6]



SWAPF 0x12,W ; Swap nibbles in d[6]



ADDWF 0x11,W ; W=~d[6]+d[5]



CALL Get_tab2 ; W=T2[W]



MOVWF 0x11 ; d[5]=T2[~d[6]+d[5]]



XORWF 0x12,f ; d[6]=d[6] XOR d[5]



SWAPF 0x11,W ; Swap nibbles in d[5]



ADDWF 0x10,W ; W=~d[5]+d[4]



CALL Get_tab2 ; W=T2[W]



MOVWF 0x10 ; d[4]=T2[~d[5]+d[4]]


 


DECF PCLATH,f ; PCLATH=2, SECA table 1 starts at offset 0x200


 


XORWF 0x11,f ; d[5]=d[5] XOR d[4]



SWAPF 0x10,W ; Swap nibbles in d[4]



ADDWF 0x13,W ; W=~d[4]+d[7]



CALL Get_tab1



MOVWF 0x13 ; d[7]=T1[~d[4]+d[7]]



XORWF 0x10,f ; d[4]=d[4] XOR d[7]



SWAPF 0x13,W ; Swap nibbles in d[7]



ADDWF 0x12,W ; W=~d[7]+d[6]



CALL Get_tab1



MOVWF 0x12 ; d[6]=T1[~d[7]+d[6]]



XORWF 0x13,f ; d[7]=d[7] XOR d[6]



SWAPF 0x12,W ; Swap nibbles in d[6]



ADDWF 0x11,W ; W=~d[6]+d[5]



CALL Get_tab1



MOVWF 0x11 ; d[5]=T1[~d[6]+d[5]]



XORWF 0x12,f ; d[6]=d[6] XOR d[5]



MOVF 0x10,W ;\ d[5]=d[5] XOR d[4]



XORWF 0x11,f ;/


 


;Step 3: get data values for the next iteration


 


INCF PCLATH,f ; PCLATH=3, block address of T2 in the external EEPROM is 3 (offset 0x300)


 


MOVF 0x11,W ;\



CALL Get_tab2 ; d[0]=d[0] XOR T2[d[5]]



XORWF 0x30,f ;/



MOVF 0x13,W ;\



CALL Get_tab2 ; d[1]=d[1] XOR T2[d[7]]



XORWF 0x31,f ;/



MOVF 0x10,W ;\



CALL Get_tab2 ; d[2]=d[2] XOR T2[d[4]]



XORWF 0x32,f ;/



MOVF 0x12,W ;\



CALL Get_tab2 ; d[3]=d[3] XOR T2[d[6]]



XORWF 0x33,f ;/



DECF PCLATH,f ; PCLATH=2, SECA table 1 starts at offset 0x200


 


; At the end there is no swap of d[0]..d[3] with d[4]..d[7].



; It is performed in Step 3.b below, which is reached in case another iteration is needed


 


; Step 4: prepare keys for the next iteration


 


CALL kbprep ; K[i+3]=K[i+3] XOR T1[K[i+4] XOR K[i-2]]



CALL kbprep_im1 ; K[i+2]=K[i+2] XOR T1[K[i+3] XOR K[i-1]]



CALL kbprep_im1 ; K[i+1]=K[i+1] XOR T1[K[i+2] XOR K
]


CALL kbprep_im1 ; K
=K XOR T1[K[i+1] XOR K[i-1]]


MOVF 0x0D,f ;\ If C=0 then return



BTFSC STATUS,Z ;/



RETURN ; Decription has been performed, return


 


; Step 3.b: Another iteration is needed, swap nibbles and decrement C


 


MOVLW 0x04 ;\ p_swap_nibble offset=4



MOVWF EEADR ;/



MOVLW 0x34 ; p_swap_nibble address=0x34



CALL p_swap_nibble ; Swap d[0]..d[3] with d[4]..d[7]



DECF 0x0D,f ; C=C-1



MOVLW 0xFC ;\ i=i-4



ADDWF 0x0F,f ;/



MOVLW 0x0C ;\



BTFSC 0x0F,07 ; If i <0 set i again to 12 (0x0C)



MOVWF 0x0F ;/



GOTO keydata_loop ; Iterate again


 


; Perform the operation K
=K XOR T1[K[i-1] XOR K[i+1] XOR C]


; 0x0F contains the "i" value and 0x0D contains the "C" value


 


kbprep_im1 DECF 0x0F,f ; Entry point for the same function, but with i -> i-1



kbprep INCF 0x0F,W ;\ Load K[i+1] into W



CALL kbget_w ;/



MOVWF 0x0C ; save it also into 0x0C



DECF 0x0F ,W ;\ Load K[i-1] into W



CALL kbget_w ;/



XORWF 0x0C,f ;K[i-1] XOR K[i+1]



CALL kbget_0f ; Read K
, the result is not used, but now FSR points to K


MOVF 0x0C,W ;\ XOR with "C"



XORWF 0x0D,W ;/



CALL Get_tab1 ; Get T1[....]



XORWF INDF,f ; and at last K
=K XOR ...


RETURN


 


; Routines to read the key byte at a given offset from the key start address 0x40



; the offset is wrapped to lie in 0x00...0x0F



; The key byte is returned in W


 


kbget_0f_p1 INCF 0x0F,f ; The key byte offset minus 1 is contained in 0x0F



kbget_0f MOVF 0x0F,W ; The key byte offset is contained in 0x0F



kbget_w ; The key byte offset is contained in W



ANDLW 0x0F ; Wrap W to lie in 0x00...0x0F



MOVWF FSR ; Set pointer to the byte offset



BSF FSR,0x06 ; Key is stored starting from 0x40



MOVF INDF,W ; Read the key byte value and store it into W



RETURN


 


;-----------------------------------------------------------------------


 


; Computes the external EEPROM address of the key to be used (from P1 in 0x0D)



; Returns in 0x10 the key offset (word address) and in PCLATH the page (block address)



; PCLATH bit 4 is set to indicate superencription


 


kaddress CLRF 0x10 ;\



RRF 0x0D,f ; Move bits 1,0 of P1 (provider number) to bits 7,6 in file register 0x10



RRF 0x10,f ; This is the same as a left shift by 6 bits (each provider uses 64 bytes (2^6))



RRF 0x0D,W ; Moroever put into W(3:0) bits 5-2 of the provider number



RRF 0x10,f ;/



ANDLW 0x03 ; Set W to bits 3-2 of provider number



MOVWF PCLATH ; which identify the page (one external EEPROM (256 bytes) contains 4 providers (4 prov*8 keys*8 bytes/key)



BSF PCLATH,0x02 ; Keys start at block address 4 in the external EEPROM (offset 0x400)



BTFSC 0x0E,07 ;\ If there is superencription



BSF PCLATH,0x04 ;/ then set bit 4 in PCLATH



MOVLW 0x07 ;\ Reduce key number P2 to lie in (0..7)



ANDWF 0x0E,f ;/



kaddr_loop MOVLW 0x08 ; Each key uses 8 bytes



DECF 0x0E,f ; Decrement key number



BTFSC 0x0E,07 ; Loop until 0x0E < 0 (exit from the loop is with 0x0E = -1 (0xff))



RETURN ; Here 0x10 contains the proper word addres for the key



ADDWF 0x10,f ; Increment word address by 8



GOTO kaddr_loop ; as many times as the key number minus one


 


;-----------------------------------------------------------------------


 


; Read a key from the external EEPROM starting from the offset specified in file register 0x10



; The key is stored in RAM starting from where the indirect register points


 


Get_key_10 MOVF 0x10,W


 


; As above, but the offset comes from W



Get_key CALL i2c_wr ; Send address to be read to external EEPROM



MOVLW 0x08 ; 8 bytes are to be read



MOVWF 0x11 ; 0x11 is the loop counter


 


Get_key_loop



CALL i2c_rd ; Read byte from external EEPROM



MOVWF INDF ; Write to RAM



INCF FSR,f ; Increment RAM pointer



DECFSZ 0x11,f ;\ Loop until the entire key is read



GOTO Get_key_loop ;/



RETURN


 


;-----------------------------------------------------------------------


 


; Routine which performs the swap of 2 blocks of eight bytes each



; W contains the starting address of the first block and EEADR contains the offset



; of the first block wrt the second



; A positive offset means the first block is after the second and a negative offset



; means the second block is after the first


 


swap_eedat ; Swap two 8-bytes blocks



CALL p_swap_nibble



GOTO swap_nibble


 


p_swap_nibble



MOVWF FSR ; Set pointer to the first block start address


 


swap_nibble ; Swap two 4-bytes blocks



CALL swap_byte



CALL swap_byte



CALL swap_byte


 


; Swap 1 byte of the first block with 1 byte of the second block



; The byte in the first block is poited by FSR, 1st block offset wrt 2nd block is into EEADR


 


swap_byte MOVF INDF,W ;\ Save 1st block byte pointed by FSR into EEDATA



MOVWF EEDATA ;/



MOVF EEADR,W ;\ Offset FSR by the block offset so it points to the 2nd byte



SUBWF FSR,f ;/



MOVF EEDATA,W ; Load 1st block byte into W



XORWF INDF,f ; Xor the two bytes and save in place of the 2nd block byte



MOVF INDF,W ; and also into W



XORWF EEDATA,f ; Xor again with the 1st block byte, so the 2nd block byte is now into EEDATA



MOVF EEDATA,W ; and also into W



XORWF INDF,f ; Xor again, so now the 1st block byte is in place of the 2nd block byte



MOVF EEADR,W ;\ Now point to the 1st block byte



ADDWF FSR,f ;/



MOVF EEDATA,W ;\ Put the 2nd block byte in place of the 1st block byte



MOVWF INDF ;/



INCF FSR,f ; Move FSR one place forward in the 1st block



RETURN


 


;-----------------------------------------------------------------------


 


;*************************************************



; function : 32 C1 CLASS instruction *



; either startup or *



; extra and general infos (package bitmap) *



;*************************************************


 


Instr_32 INCF PCLATH,f ; External EEPROM page 1 \ The startup answer is stored in



MOVLW 0x99 ; Address 0x99 / external EEPROM address 0x199



BTFSS 0x40,00 ; If the last received byte was not 0x01 (from C1 34)



GOTO pbmap ; then jump to extra and general infos (package bitmap)



GOTO COMM_EEPR ; else transmit data from external EEPROM (startup) starting from 0x199


 


;-----------------------------------------------------------------------


 


; Write a byte sequence to external EEPROM



; The byte sequence is stored starting from RAM address 0x38, and its length is stored in 0x0F



; The external EEPROM internal address pointer should have been set previously



; by a control byte, word address write sequence


 


wr_i2c_string



MOVLW 0x37 ;\ Load pointer (one location lower since the loop starts by incrementing the address)



MOVWF FSR ;/ to RAM



wr_i2c_str_loop



INCF FSR,f ;\ Read next byte



MOVF INDF,W ;/



CALL i2cw_byte ; Send to EEPROM



DECFSZ 0x0F,f ;\ Loop until all bytes are sent



GOTO wr_i2c_str_loop;/



GOTO i2c_stop ; Stop transfer to EEPROM


 


;-----------------------------------------------------------------------


 


Rec_skip_r SUBWF 0x0F,f ; Receive and discard the number of bytes stored at RAM location 0x0F minus the number of bytes stored in W


 


Rec_skip CALL Receive ; Receive and discard the number of bytes stored at RAM location 0x0F



DECFSZ 0x0F,f



GOTO Rec_skip



RETURN


 


;=======================================================================



; RB7 I/O procedures



;=======================================================================


 


; Send the data byte contained in W to RB7


 


Send


 


IF LED ;\



BSF PORTA,LED_GREEN; Green LED on



ENDIF ;/


 


MOVWF 0x16 ; Store the data byte into 0x16



MOVLW T_SEND_START ;\ Pause



CALL Pause ;/



MOVLW 0x7F ;\ Define PORT B I/O RB7=output, all others=input



TRIS PORTB ;/



CLRF 0x17 ; Clear 0x17, used for parity



BCF PORTB,07 ; Send start bit



MOVLW 0x08 ;\ Length = 8, load counter



MOVWF 0x14 ;/


 


send_loop CALL Std_pause ; Wait



RRF 0x16,f ;\ Load bit to be transmitted in bit 7 of W



RRF 0x16,W ;/



ANDLW 0x80 ; Clear bits 6:0 of W



XORWF 0x17,f ; Update parity



XORWF PORTB,W ; Read PORT B data into W xoring bit 7 (RB7) \ merge bit 7 of W



XORWF PORTB,f ; Write W to PORT B xoring bit 7 again / into PORT B



DECFSZ 0x14,f ;\ Cycle



GOTO send_loop ;/


 


CALL Std_pause ; Wait



MOVF 0x17,W ;\



XORWF PORTB,W ; Send parity



XORWF PORTB,f ;/



CALL Std_pause ; Wait



MOVLW 0xFF ;\ Define PORT B I/O = all input



TRIS PORTB ;/


 


IF LED



BCF PORTA,LED_GREEN; Green LED off



ENDIF


 


MOVLW T_SEND_STOP ;\ Pause



GOTO Pause ;/


 


;-----------------------------------------------------------------------


 


; Wait for input on RB7, receive one byte of data from RB7 and return it through W


 


Receive BTFSC PORTB,07 ;\ Read PORT B, loop while 1 on RB7



GOTO Receive ;/ THIS IS THE MAIN LOOP


 


IF LED ;\



BSF PORTA,LED_GREEN; Green LED on



ENDIF ;/


 


MOVLW T_RECEIV_START ;\ 0 (start bit) has been seen on RB7: pause



CALL Pause ;/



MOVLW 0x09 ; Length = 9 (1 byte data + 1 bit parity)



MOVWF 0x14 ; Counter


 


Receive_loop



BCF STATUS,C ; Clear carry flag



BTFSC PORTB,07 ; Read PORT B



BSF STATUS,C ; 1 on RB7, set carry flag



RRF 0x16,f ; 0 on RB7, rotate right



CALL Std_pause



DECFSZ 0x14,f ; Decrement counter



GOTO Receive_loop ; Repeat


 


RLF 0x16,f ; Done, rotate left to skip parity bit



MOVLW T_RECEIV_STOP ;\ Pause



CALL Pause ;/



MOVF 0x16,W ; Return received byte in W


 


IF LED ;\



BCF PORTA,LED_GREEN; Green LED off



ENDIF ;/


 


RETURN


 


;-----------------------------------------------------------------------


 


Std_pause MOVLW T_SERIAL ; Standard pause for reading/writing via serial protocol


 


Pause MOVWF 0x15 ; Pause for the time stored in W


 


Pause_loop DECFSZ 0x15,f ;\ Loop until pause expires



GOTO Pause_loop ;/



RETLW 0x00 ; Return always 0


 


;=======================================================================



; External EEPROM R/W procedures



;=======================================================================


 


; ACK polling, tries to write a control byte until ACK


 


I2C_busy CALL i2c_start



BCF STATUS,C ; Clear carry flag, R/W bit = 0 (write)



CALL i2cw_conbyte ; Write control byte, returns ACK into carry



BTFSC STATUS,C ; Skip if not busy



GOTO I2C_busy ; Loop while busy


 


RETURN


 


;-----------------------------------------------------------------------


 


; Read a byte from the PIC EEPROM



; The address is read from W and the read value is returned in W


 


Rd_eeprom MOVWF EEADR ; Load address



BSF STATUS,RP0 ; Select page 1 (80H - FFH)



BSF EECON1,0x00



BCF STATUS,RP0 ; Select page 0 (00H - 7FH)



MOVF EEDATA,W ; Return value



RETURN


 


;-----------------------------------------------------------------------


 


; Send a byte sequence from the external EEPROM to the serial line



; The block select bits (high address) comes from PCLATH and the word address (low byte) comes from W



; 0x0F contains the number of bytes to be sent


 


EEPROM_send CALL i2c_wr ; Send address


 


eepr_send_loop



DECF 0x0F,f ; Decrement counter



BTFSC 0x0F,07 ;\ If all bytes have been read then return



RETURN ;/



CALL i2c_rd ; Read byte



CALL Send ; Send to serial line



GOTO eepr_send_loop


 


; Returns in W the external EEPROM byte with block address givan by PCLATH(2:0) and



; word address given by W.



; In case PCLATH(2:0) is 3, it returns in W the SECA algorythm table 2 value



; corresponding to the value contained in W (since T2 is in external EEPROM page 3)



Get_tab2 MOVWF EEADR ; Save W into EEADR



CALL i2c_start



BCF STATUS,C ; Clear carry flag, next i2c access is for writing



CALL i2cw_conbyte ; Send control byte to i2c



MOVF EEADR,W ; Reload W from EEADR



CALL i2cw_byte ; Send word address to i2c


 


;-----------------------------------------------------------------------


 


; Read the external EEPROM byte specified by W and PCLATH



; The external EEPROM internal address pointer should have been set previously



; by a control byte, word address write sequence



; The value is returned in W


 


i2c_rd CALL i2c_start



BSF STATUS,C ; Set carry flag, next i2c access is for reading



CALL i2cw_conbyte ; Send again control byte to i2c



CALL i2cr_byte ; Read byte from i2c into EEDATA



CALL i2c_stop



MOVF EEDATA,W ; Return read byte in W



RETURN


 


;-----------------------------------------------------------------------


 


; Writes a complete address (control byte + word address) to the external EEPROM



; block address is in PCLATH(2:0) and word address is in W


 


i2c_wr MOVWF EEADR ; Save word address



CALL I2C_busy ; Loop writing cotrol byte until ACK



MOVF EEADR,W ; Recover word address



GOTO i2cw_byte ; Write it


 


; Write a data byte to external EEPROM



; The external EEPROM internal address pointer should have been set previously



; by a control byte, word address write sequence


 


wr_last CALL i2cw_byte



GOTO i2c_stop


 


;-----------------------------------------------------------------------


 


; Build control byte into W from block address into PCLATH(2:0) and R/W bit into carry flag


 


i2cw_conbyte



RLF PCLATH,W ; Load block select bits from PCLATH and R/W bit from carry into W



ANDLW 0x0F ; Clear space for control code bits



IORLW 0xA0 ; Load control code bits 1010 into W, control byte in W is complete


 


; Send a byte stored in W to external EEPROM



i2cw_byte MOVWF EEDATA ; Store W into EEDATA



MOVLW 0xCF ;\ Define PORT B I/O RB4,RB5=output, all others=input



TRIS PORTB ;/



CALL i2cw_nibble ;\ Write byte contained in EEDATA



CALL i2cw_nibble ;/



GOTO i2cr_bit ; Read ACK


 


; Send a nibble from EEDATA to external EEPROM



i2cw_nibble



CALL i2cw_nibble_2 ; 1st bit



CALL i2cw_nibble_2 ; 2nd bit



CALL i2cw_nibble_2 ; 3rd bit, 4th bit below


 


; Send an EEDATA bit to external EEPROM



i2cw_nibble_2



RLF EEDATA,f ; Put bit to be sent into carry



GOTO i2cw_bit_x ; Send


 


; Read a byte from external EEPROM into EEDATA



i2cr_byte MOVLW 0xDF ;\ Define PORT B I/O RB5=output, all others=input



TRIS PORTB ;/



CALL i2cr_nibble ;\ Read byte



CALL i2cr_nibble ;/



BSF STATUS,C ; Set carry flag



GOTO i2cw_bit ; NACK, stop


 


; Read a nibble form external EEPROM int EEDATA



i2cr_nibble CALL i2cr_nibble_2 ; 1st bit



CALL i2cr_nibble_2 ; 2nd bit



CALL i2cr_nibble_2 ; 3rd bit, 4th bit below


 


; Read a bit from external EEPROM into EEDATA



i2cr_nibble_2



CALL i2cr_bit_x ; Read bot into carry



RLF EEDATA,f ; Store into EEDATA



RETURN


 


;-----------------------------------------------------------------------


 


; Init data transfer from/to external EEPROM



i2c_start BSF PORTB,0x04



MOVLW 0xCF ;\ Define PORT B I/O RB4,RB5=output, all others=input



TRIS PORTB ;/



BSF PORTB,0x05 ; Clock high



NOP



BCF PORTB,0x04 ; Data start



GOTO clock_low


 


;-----------------------------------------------------------------------


 


; Stop data transfer from/to external EEPROM



i2c_stop BCF PORTB,04 ; Data start



MOVLW 0xCF ;\ Define PORT B I/O RB4,RB5=output, all others=input



TRIS PORTB ;/



NOP



BSF PORTB,05 ; Clock high



NOP



BSF PORTB,04 ; Data stop



nclock_low NOP



clock_low BCF PORTB,05 ; Clock low



RETURN


 


i2cw_bit MOVLW 0xCF ;\ Define PORT B I/O RB4,RB5=output, all others=input



TRIS PORTB ;/


 


; Actual bit write to RB4 (external EEPROM)



; Bit to be written is from carry



i2cw_bit_x



BTFSS STATUS,C ; Skip if carry set



BCF PORTB,04



BTFSC STATUS,C ; skip if no carry



BSF PORTB,04



BSF PORTB,05 ; Clock high



GOTO nclock_low


 


;-----------------------------------------------------------------------


 


i2cr_bit MOVLW 0xDF ;\ Define PORT B I/O RB5=output, all others=input



TRIS PORTB ;/


 


; actual bit read from RB4 (external EEPROM)



; bit is read into carry



i2cr_bit_x BSF PORTB,05 ; Clock high



NOP



BSF STATUS,C ; Set carry flag



BTFSS PORTB,04



BCF STATUS,C ; Clear carry flag



GOTO clock_low


 


;=======================================================================



; SECA Table 1



;=======================================================================


 


; Returns in W the SECA algorythm table 1 value corresponding to the value contained in W



; Before calling this routine PCLATH should have the value 2, since the table starts at offset 0x200


 


Get_tab1 MOVWF PCL ; Absolute addressing


 


ORG 0x200


 


dt 0x2A,0xE1,0x0B,0x13,0x3E,0x6E,0x32,0x48



dt 0xD3,0x31,0x08,0x8C,0x8F,0x95,0xBD,0xD0



dt 0xE4,0x6D,0x50,0x81,0x20,0x30,0xBB,0x75



dt 0xF5,0xD4,0x7C,0x87,0x2C,0x4E,0xE8,0xF4



dt 0xBE,0x24,0x9E,0x4D,0x80,0x37,0xD2,0x5F



dt 0xDB,0x04,0x7A,0x3F,0x14,0x72,0x67,0x2D



dt 0xCD,0x15,0xA6,0x4C,0x2E,0x3B,0x0C,0x41



dt 0x62,0xFA,0xEE,0x83,0x1E,0xA2,0x01,0x0E



dt 0x7F,0x59,0xC9,0xB9,0xC4,0x9D,0x9B,0x1B



dt 0x9C,0xCA,0xAF,0x3C,0x73,0x1A,0x65,0xB1



dt 0x76,0x84,0x39,0x98,0xE9,0x53,0x94,0xBA



dt 0x1D,0x29,0xCF,0xB4,0x0D,0x05,0x7D,0xD1



dt 0xD7,0x0A,0xA0,0x5C,0x91,0x71,0x92,0x88



dt 0xAB,0x93,0x11,0x8A,0xD6,0x5A,0x77,0xB5



dt 0xC3,0x19,0xC1,0xC7,0x8E,0xF9,0xEC,0x35



dt 0x4B,0xCC,0xD9,0x4A,0x18,0x23,0x9F,0x52



dt 0xDD,0xE3,0xAD,0x7B,0x47,0x97,0x60,0x10



dt 0x43,0xEF,0x07,0xA5,0x49,0xC6,0xB3,0x55



dt 0x28,0x51,0x5D,0x64,0x66,0xFC,0x44,0x42



dt 0xBC,0x26,0x09,0x74,0x6F,0xF7,0x6B,0x4F



dt 0x2F,0xF0,0xEA,0xB8,0xAE,0xF3,0x63,0x6A



dt 0x56,0xB2,0x02,0xD8,0x34,0xA4,0x00,0xE6



dt 0x58,0xEB,0xA3,0x82,0x85,0x45,0xE0,0x89



dt 0x7E,0xFD,0xF2,0x3A,0x36,0x57,0xFF,0x06



dt 0x69,0x54,0x79,0x9A,0xB6,0x6C,0xDC,0x8B



dt 0xA7,0x1F,0x90,0x03,0x17,0x1C,0xED,0xD5



dt 0xAA,0x5E,0xFE,0xDA,0x78,0xB0,0xBF,0x12



dt 0xA8,0x22,0x21,0x3D,0xC2,0xC0,0xB7,0xA9



dt 0xE7,0x33,0xFB,0xF1,0x70,0xE5,0x17,0x96



dt 0xF8,0x8D,0x46,0xA1,0x86,0xE2,0x40,0x38



dt 0xF6,0x68,0x25,0x16,0xAC,0x61,0x27,0xCB



dt 0x5B,0xC8,0x2B,0x0F,0x99,0xDE,0xCE,0xC5


 


;-----------------------------------------------------------------------


 


;*************************************************



; function : 3A C1 CLASS instruction *



; request for the control word *



; command : C1 3A 00 00 10 *



; answer : 3A 10 10 55 E6 55 54 05 80 04 14 40 *



; 8F 40 41 11 23 90 00 *



;*************************************************



; This instruction asks for the decrypted control words previously issued by an instruction C1 3C



; The decrypted values were stored starting from RAM address 0x30



; Here a loop reads the values through the indirect register and sends them


 


Instr_3A MOVLW 0x30 ;\ Point to RAM address 0x30



MOVWF FSR ;/



instr_3A_loop



MOVF INDF,W ; Read value



CALL Send ; send it



INCF FSR,f ; Next value



DECFSZ 0x0F,f ;\ Loop for the lenght stored in 0x0F



GOTO instr_3A_loop ;/



GOTO TX9000 ; Send status bytes


 


;*************************************************



; function : 34 C1 CLASS instruction *



; request for the control word *



;*************************************************


 


Instr_34 CALL Rec_skip ; Discard the received bytes



MOVWF 0x40 ; Save the last received byte in 0x40 (0x01:startup, 0x00:package bitmap)



GOTO TX9000 ; Transmit OK


 


;*************************************************



; function : 30 C1 CLASS instruction *



; PIN CONTROLLED OPERATIONS *



;*************************************************


 


Instr_30 MOVLW 0x02



CALL Rec_skip_r ; Receive and discard everithing but the last 2 bytes (PIN), returns with 0x0F=0



CALL Receive ; Receive the first PIN byte



IORWF 0x0F,f ; Save it into 0x0F



ANDLW 0x0F ;\ Low nibble into 0x0C



MOVWF 0x0C ;/



CALL Receive ; Receive the second PIN byte



MOVWF 0x0D ; Save it into 0x0D



IORWF 0x0F,f ; IOR with the first PIN byte



MOVF 0x0E,f ;\



BTFSS STATUS,Z ; If P2 is not 0 then transmit status bytes



GOTO TX9000 ;/



INCF PCLATH,f ;\ PCLATH=1 \ Point to 0x190 in the external EEPROM



MOVLW 0x90 ;/ W=0x90 /



; Initialization



MOVF 0x0F,f ;\ If (1st PIN byte) IOR (2nd PIN byte) = 0



BTFSC STATUS,Z ;/ (i.e. if both bytes are 0)



GOTO wr190 ; then write 0x91 to external EEPROM position 0x190 and transmit status bytes



; Load next external EEPROM offset to be written (points to the next byte of the key to be written)



CALL Get_tab2 ; else read external EEPROM position 0x190 into W



MOVWF 0x0F ; and into 0x0F too


 


; Apparently, the byte at offset 0x190 in the external EEPROM (here just loaded into 0x0F)



; contains the offset in page 1 of the next new key byte to be written in 0x191-0x198 (in the external EEPROM).



; Since the new key starts at 0x191, offset 0x190 initially contain 0x91.



; Moreover, if bit 6 of the byte at offset 0x190 is 1, then the high nibble at that offset has



; already been written, so it is re-read, combined with the low nibble of the 1st PIN byte,



; and then rewritten at the following location, writing the 2nd PIN byte in its place



;



; A call with PIN 0000 is needed to initialize external EEPROM offsewt 0x190 to 0x91.



; After that, the key update strategy is 3 nibbles per call, as follows:



;



; 1st call: xx = PIN 2, x=PIN 1 low



; 2nd call: yy = PIN 2, y=PIN 1 low



; 3rd call: zz = PIN 2, z=PIN 1 low



; 4th call: pp = PIN 2, p=PIN 1 low



; 5th call: qq = PIN 2, q=PIN 1 low



; 6th call: rr = PIN 2, r=PIN 1 low



; This is the image of the external EEPROM 0x190-0x198:



; before 1st call: 0x91 00 00 00 00 00 00 00 00



; after 1st call: 0xD2 xx x- -- -- -- -- -- --, since 0x92 XOR 0x40 = 0xD2



; after 2nd call: 0x94 xx yy xy -- -- -- -- --



; after 3rd call: 0xD5 xx yy xy zz z- -- -- --, since 0x95 XOR 0x40 = 0xD5



; after 4th call: 0x97 xx yy xy zz pp zp -- --



; after 5th call: 0xD8 xx yy xy zz pp zp qq q-, since 0x95 XOR 0x40 = 0xD8



; On the 6th call the key is written as



; xx yy xy zz pp zp qq qr



; to the external EEPROM at block address rr(2:0)



; and word address rr(7:3)



;



; PIN 0000 is also used to reset yellow and green LEDs on subscription date update



; and key update respectively


 


BTFSS 0x0F,0x06 ; If bit 6 in W was 0



GOTO wr19x ; then goto wr19x (no spare nibble from the previous call)


 


BTFSC 0x0F,0x03 ;\ If all the 8 key bytes have been received



GOTO Remote_kupdate ;/ then update EEPROM key


 


XORLW 0x40 ; else flip bit 6 in W (set it to 0)



CALL Get_tab2 ; and read external EEPROM byte with word address W and block address 1



; i.e., read previous spare nibble



; Combine previous and current spare nibbles



IORWF 0x0C,f ;\ IOR W (from external EEPROM) and the low nibble of the first PIN byte



SWAPF 0x0C,f ;/ and swap nibbles in the result (in 0x0C)



MOVF 0x0F,W ; Set W to the byte read from external EEPROM position 0x190



XORLW 0x40 ; and flip bit 6 of W (set it to 0)



INCF 0x0F,f ; Increment key bytes pointer


 


wr19x CALL i2c_wr ; set pointer to external EEPROM as specified by W



MOVF 0x0D,W ;\ Write 2nd PIN byte



CALL i2cw_byte ;/



SWAPF 0x0C,W ;\ Write 1st PIN byte low nibble as high nibble on calls 1,3,5



CALL wr_last ;/ or combined with previous 1st PIN byte low nibble on calls 2,4



; CALL i2c_delay



MOVLW 0x40 ;\ Move key bytes pointer to W and flip bit 6



XORWF 0x0F,W ;/


 


; Write W+1 to external EEPROM position 0x190



wr190 MOVWF 0x0F ;\ Save W+1 into 0x0F



INCF 0x0F,f ;/ (increment key bytes pointer)



MOVLW 0x90 ;\ Set external EEPROM pointer to 0x190



CALL i2c_wr ;/



MOVF 0x0F,W ;\ Write there W+1



CALL wr_last ;/



; CALL i2c_delay



IF LED ;\



BCF PORTA,LED_YELLOW ; Yellow LED is set off



BCF PORTA,LED_RED ; Red LED is set off



BCF PORTA,LED_GREEN2 ; Green2 LED is set off



ENDIF ;/



GOTO TX9000 ; Transmit status bytes


 


;-----------------------------------------------------------------------


 


; Actualize a key stored in EEPROM from the key stored into RAM via remote



Remote_kupdate



MOVLW 0x38 ;\ Set pointer to RAM address 0x38



MOVWF FSR ;/



MOVLW 0x91 ;\ Read key starting from external EEPROM offset 0x191



CALL Get_key ;/ (since PCLATH has been set to 1) and store it into RAM from position 0x38



MOVF 0x0C,W ;\ IOR the last byte of the key with the low nibble of the last PIN byte 1 received



IORWF 0x3F,f ;/



CLRF PCLATH ; reset PCLATH to 0



MOVF 0x0D,W ;\



ANDLW 0x07 ; Set external EEPROM block address to bits (2:0) of the last PIN byte 2 received



ADDWF PCLATH,f ;/



MOVF 0x0D,W ;\ Set external EEPROM word address to bits (7:3) of the last PIN byte 2 received



ANDLW 0xF8 ;/



CALL i2c_wr ; Set external EEPROM pointer



MOVLW 0x08 ;\



MOVWF 0x0F ; Write the 8 bytes key from RAM offset 0x38 to external EEPROM



CALL wr_i2c_string ;/


 


IF LED ;\



BSF PORTA,LED_RED ; Red LED is set and left on if key updated



ENDIF ;/


 


GOTO TX9000 ; transmit 9000


 


;**************************************************



; function : C1 40 CLASS instruction *



; ENTITLEMENT MANAGEMENT MESSAGE *



;**************************************************



; c14003814e



;



; 4b c8 7c 75 ab 0b 84 84 96 f1 d3 f7 ee 94 96 c0



; b1 51 cc 39 a7 b6 08 c4 a1 50 39 0d 00 b0 df 73



; e9 d6 6c c3 d5 ec 8e d6 0f 7b 1f 9b 74 48 f7 7b



; cc 97 d8 60 da 91 e9 c3 d7 03 8b b1 a0 7f de 50



; 5c 56 2f 8b b2 c9 e3 39



; da 86 dd a7 34 d1



; 90 00


 


; decoder



; f0 5b 08 02 04 45 02 08 ce b4 01 42 04 50 aa 76



; b7 10 01 42 13 0e 2b 11 a4 50 48 60 32 2c 10 11


 


; 12 22 15 1f



; 21 ;nano data



; 15 5f ;data



; 90 5d ;nano primary key | key d



; d9 5f e0 f4 66 94 29 ab



; 90 5c ;nano primary key | key c



; 15 3f bb df 11 bb e5 30



; 90 5e ;nano primary key | key e



; 68 19 ba 23 4b c4 1b 07



;



; 82 ;\ signature



; 27 c9 da 86 dd a7 34 d1 ;/



;



; Subscription 31/10/2000



; primary key 0d



; primary key 0c



; primary key 0e


 


; index=01



; key=42 22 7b 71 20 34 93 ef



; index=0c



; key=d9 cb b8 5c 57 af 2d 53



; index=0d



; key=61 24 8c d4 1a 39 2a ad



; index=0e



; key=5a 1d b3 dd 48 22 12 31


 


Instr_40



MOVF 0x0D,W ; Save P1 into W



MOVWF 0x17 ; and into file register 0x17


 


BSF PCLATH,0x03 ; Set PCLATH(3) to 1 (next call to TX9000 will transmit 901D)


 


MOVLW 0x34 ;\



SUBWF 0x0F,W ; If length is less than 0x34 bytes



BTFSS STATUS,C ; then jump to process instruction 34 (i.e., discard received data and transmit status bytes)



GOTO Instr_34 ;/



CALL GET_CW_loop ; else receive the remaining part of the command (only the last 0x31 bytes are retained),



; read the 16 bytes key from the external EEPROM according to P1 and P2,



; and in case of superencription implement the first decription


 


BSF PCLATH,0x03 ; Set PCLATH(3) to 1 (next call to TX9000 will transmit 901D)


 


MOVF 0x17,W ; Recover P1 from file register 0x17



ANDLW 0x0F ;\



BTFSC STATUS,Z ; If P1 is 0 (SECA) transmit 901D


 

 
Maakt niet uit, het is toch al voldoende voor de nodige uurtjes puzzelplezier....

Dreeke :)

 
Yeah!!!!!!!!!!!!!!!

De puzzel is nu toch bijna opgelost.........

De sleutel: toch Picachu! Wat een mooi proggie.

Eerst de secanix hexfile en eeprom geladen, vervolgens de "break" neergezet in de assemblercode, daar waar de C1 3C instructie wordt "aangepakt", en vervolgens het RAM/EEdata-window geopend.

Dan de emulator gestart (met de season natuurlijk) en zodra de Ins C1 3C binnenkomt met de F10 toets stap voor stap iedere instructie doorlopen (je krijgt er wel een "lam" vingertje van ;) ). De RAM laat dan precies zien wat er gebeurt met het CW en de "round"-key. Wow!

Voor een decodering met alleen een primarykey werkt mijn spreadsheet nu al perfect.

Er zat dus echt een heel grote fout in de Media1.doc (je zou ook kunnen zeggen: een zeer grote onduidelijkheid) en in de seca.xls.

Die is er nu UIT. En het werkt :biggrin: .

Jammergenoeg nog niet met zowel een primary als een secundary key, maar de oplossing is nu wel nabij......

We zoeken nog even verder ;)

 
De aanhouder wint dus toch........... :biggrin:

Nadat ik een darksuca.hex en -.bin in Picachu had geladen (voor de secundaire keys) en nogmaals stap voor stap het decoderingsproces heb doorlopen, bleken er ook nog enkele "overname"-fouten in de hash-tabellen van de originele seca.xls te zitten (en dus ook in mijn quattro pro-sheet :sad: ).

Nu de seca.xls geheel is aangepast werkt-ie perfect, zowel voor coderen als decoderen en zowel met alleen de prim.key als met prim.- en sec.key.

Zou de schrijver van de seca.xls een doel hebben gehad met de daarin opgesloten fouten ;) ............

 



Hosting Fun

Advertenties

Terug
Bovenaan Onderaan