PDA

View Full Version : Seca algo


Kcplus
02-07-2002, 06:27
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?

Kcplus
05-07-2002, 03:15
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 :D ;
- of de echte cracks denken: "zoek het even lekker zelf uit!" :p ;
- of het is echt te moeilijk, dus waar ben ik aan begonnen :(
- of .......................... :eek:

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

snif

petertje
05-07-2002, 04:45
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

satelliet
05-07-2002, 06:07
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.

alexje
05-07-2002, 13:10
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

Kcplus
06-07-2002, 06:31
@alexje
Of ik de faq van RvG wel eens ben tegengekomen? Man, ik ken dat ding bijna helemaal uit mijn hoofd ;) :D .

@ 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................

Kcplus
10-07-2002, 01:04
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 :D .

FranX
12-07-2002, 05:10
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

alexje
12-07-2002, 13:21
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 8)

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[i]=K[i] 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[i] and store it into W
XORWF 0x34,W ; W=d[4] XOR K[i]
CALL Get_tab1
MOVWF 0x10 ; [0x10]=T1[d[4] XOR K[i]]
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[i]]
CALL kbprep_im1 ; K[i]=K[i] 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[i]=K[i] 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[i], the result is not used, but now FSR points to K[i]
MOVF 0x0C,W ;\ XOR with "C"
XORWF 0x0D,W ;/
CALL Get_tab1 ; Get T1[....]
XORWF INDF,f ; and at last K[i]=K[i] 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
GOTO TX9000 ;/
MOVLW 0x13 ; Load 0x13 in W (so in the following the last 0x13 received bytes are processed)

; Hereafter nanos 0x90 and 0x21 are probed
; Upon loop entry FSR is set at the end of received data minus 0x13, which skips
; the last 0x09 received bytes (signature) plus 0x0A bytes which correspond to
; a set of nano 0x90 (1 byte), key index (1 byte) and key value (8 bytes).
; Several of these 0x0A bytes sets corresponding to nanos 0x90 can be processed
; by the loop

ins_40_loop SUBWF 0x14,f ;\ Point to the end of the received data
MOVF 0x14,W ; minus the offset contained in W
MOVWF FSR ;/ (0x13 on loop entry (0x0A+0x09), otherwise 0x0A)
MOVLW 0x18 ;\
SUBWF FSR,W ; If we are pointing before 0x18 (start of received data)
BTFSS STATUS,C ;/
GOTO Comp_date ; then process nano 0x21, since there are less than 0x0A bytes left to be processed
MOVF INDF,W ;\
XORLW 0x90 ; else check if we are pointing 0x90 (nano primary key)
BTFSS STATUS,Z ;/
GOTO TX9000 ; If not nano 0x90, then transmit status bytes 901D

MOVF FSR,W ;\
SUBLW 0x0A ; Swap offset is 0x0A-FSR
MOVWF EEADR ;/
MOVLW 0x0C ; Swap 1st block start is at 0x0C,
; so 2nd block start is at 0x0C-0x0A+FSR=FSR+2,
; that is at the received primary key start
CALL swap_eedat ; Load primary key into 0x0C-0x13
CALL swap_24_30 ; Swap 0x0C-0x13 with 0x30-0x37 (swap old and new primary key)
CALL swap_2C_38 ; Load old primary key into 0x38-0x3F
CALL Decrypt ; Decrypt
CALL swap_F8_30 ; Restore old primary key in 0x30-0x37 and put decrypted new primary key into 0x38-0x3F
CALL Comp_key ; Write new primary key to EEPROM
MOVLW 0x0A ; Move pointer 0x0A bytes backward
GOTO ins_40_loop

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

; Actualize the subscription date

; Here W has been decremented by 0x0A from either the last nano 0x90 processed or from the signature
; and then decremented by 0x18 again.
; Since the ins. 0x21 sequence is only 3 bytes long, we need to add first 0x18 to W to recover the last
; 0x18 decrement and then 0x07 to recover 7 bytes from the 0x0A decrement in order to point at the start
; of the ins. 0x21 sequence, i.e. 0x18+0x07=0x1F

Comp_date ADDLW 0x1F ;\ Add 0x18+0x07 to W
MOVWF FSR ;/
MOVF INDF,W ; Read pointed value
XORLW 0x21 ;\ If not nano 0x21
BTFSS STATUS,Z ;/
GOTO TX9000 ; then transmit status bytes 901D
CLRF PCLATH ; else reset PCLATH (set block address to 0 and transmit 9000 on the next TX9000 call)
MOVLW 0x0E ; Initial offset: provider 0 subscription date in the external EEPROM starts at 0x0E+0x18
INCF 0x17,f ; Increment P1 by 1 to add 0x18 to the 0x0E offset on the first Comp_date_loop iteration

Comp_date_loop
ADDLW 0x18 ; Each provider user 0x18 bytes
BTFSC STATUS,C ;\ Set block address to 1 if we reach 0x100
INCF PCLATH,f ;/
DECFSZ 0x17,f ;\ Iterate until the proper subscription date offset is loaded into W
GOTO Comp_date_loop ;/

MOVWF 0x0C ; Save the offset into 0x0C
CALL i2c_wr ; Write address to external EEPROM
INCF FSR,F ; Point to 1st byte of the new date
CALL i2c_rd ;\
XORWF INDF,W ; If this is not equal to the 1st byte of the old date from internal EEPROM
BTFSS STATUS,Z ;/
GOTO Wr_date ; then write new subscription date to external EEPROM
INCF FSR,f ; Now point to 2nd byte of the new date
CALL i2c_rd ;\
XORWF INDF,W ; If it is equal to the 2nd byte of the old date from internal EEPROM
BTFSC STATUS,Z ;/
GOTO TX9000 ; then transmit status bytes 9000
DECF FSR,f ; else point to the 1st byte of the new suscription date

; Update suscription date in the external EEPROM
Wr_date MOVF 0x0C,W ; Recover subscription date offset in the external EEPROM
CALL i2c_wr ; Write address to external EEPROM
MOVF INDF,W ; Load 1st byte
CALL i2cw_byte ; and write it
INCF FSR,f ;\ Load 2nd byte
MOVF INDF,W ;/
CALL wr_last ; and write it
; CALL i2c_delay

IF LED ;\
BSF PORTA,LED_RED ; Red LED is set and left on if subscription date updated
ENDIF ;/

GOTO TX9000

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

; Intruction 0x40, nano 0x90, new primary key (external EEPROM update)

Comp_key INCF 0x14,W ;\
MOVWF FSR ; Recover key index (at start of nano 0x90 + 1)
MOVF INDF,W ;/
MOVWF 0x0E ; and put it into 0x0E
MOVF 0x17,W ; Recover P1 from file register 0x17
MOVWF 0x0D ; and put it into 0x0D
CALL kaddress ; Compute key address in the external EEPROM
MOVF 0x10,W ;\ and send it to external EEPROM
CALL i2c_wr ;/
MOVLW 0x38 ;\ point to decrypted new primary key
MOVWF FSR ;/

; Compare old and new keys, update EEPROM if they are not the same
Comp_key_loop
CALL i2c_rd ; Read 1 byte of the old key from external EEPROM
XORWF INDF,W ;\ If it is not the same as the new key
BTFSS STATUS,Z ;/
GOTO Wr_key ; then write the entire new key to external EEPROM
INCF FSR,f ; Select next new key byte
BTFSC FSR,0x03 ;\ Repeat until 0x40 is reached (8 bytes total)
GOTO Comp_key_loop ;/

RETURN

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

; Write a key to external EEPROM
Wr_key
MOVF 0x10,W ; Word address for the external EEPROM
CALL i2c_wr ; Send control byte and word address to external EEPROM
MOVLW 0x08 ;\ 8 bytes are to be written
MOVWF 0x0F ;/
CALL wr_i2c_string ; Write key to external EEPROM

IF LED ;\
BSF PORTA,LED_RED ; Red LED is set and left on if key updated
ENDIF ;/

RETURN

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

swap_24_30 MOVLW 0x24
MOVWF EEADR
MOVLW 0x30
CALL swap_eedat
RETURN

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

swap_2C_38 MOVLW 0x2C
MOVWF EEADR
MOVLW 0x38
CALL swap_eedat
RETURN

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

; Package bitmap, answer to C1 32

pbmap MOVF 0x0D,f ;\ Test P1
BTFSC STATUS,Z ;/
GOTO nano_04 ; If 0 (provider SECA), then no package bitmap is available
MOVLW 0x83 ;\ Nano 83, a package bitmap follow
CALL Send ;/
DECF 0x10,f ; 0x10 contained the length, decrement by one since nano 83 was sent
MOVLW 0x08 ;\ Set number of bytes to be transmitted from external EEPROM to 8
MOVWF 0x0F ;/
SUBWF 0x10,f ; Decrement 0x10 (total number of bytes to be transmitted) accordingly
BCF STATUS,C ; Clear carry flag
RLF 0x0D,f ;\
RLF 0x0D,f ; Multiply P1 by 8 and put it into W (each package bitmap answer is 8 bytes long)
RLF 0x0D,W ;/ to provide correct offset for provider P1
INCF PCLATH,f ; Package bitmaps start at offset 0x200 into external EEPROM (block address 2)
CALL EEPROM_send ; Transmit package bitmap

nano_04 MOVLW 0x04 ; Nano 04: no information available

; The following loop sends the byte contained in W followed by
; a number of fillers (0xFF) which is the content of file register 0x10 minus one

send_w_fill CALL Send
MOVLW 0xFF
DECFSZ 0x10,f
GOTO send_w_fill

GOTO TX9000 ; Send status bytes

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

; Seca044: external EEPROM read ?
; Send to CAM a byte sequence starting from the external EEPROM address with block address P1
; and word address P2
; The byte sequence length is specified by 0x0F

Instr_21 MOVF 0x0D,W ; Load P1 into W
ADDWF PCLATH,f ; into PCLATH, too
MOVF 0x0E,W ; Load P2 into W
CALL i2c_wr ; Select address into external EEPROM

inst_21_loop
CALL i2c_rd ;\ Read byte from external EEPROM and transmit to CAM
CALL Send ;/
DECFSZ 0x0F,f
GOTO inst_21_loop

GOTO TX9000 ; Send status bytes

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

;*************************************************
; function : 22 C1 CLASS instruction *
; key update ? *
; receive an 8 bytes sequence and store it both *
; into RAM starting from address 0x038 and into *
; the external EEPROM *
;*************************************************

Instr_22 MOVLW 0x38 ;\ The received sequence will be stored starting from RAM address 0x38
MOVWF FSR ;/
instr_22_loop
CALL Receive ;\ Receive one byte
MOVWF INDF ; and store it via the indirect register
INCF FSR,f ; Point to the next byte
BTFSS FSR,06 ; until RAM address 64 is reached (so 8 bytes total are stored)
GOTO instr_22_loop ;/
MOVF 0x0D,W ;\ P1=block address for the external EEPROM
ADDWF PCLATH,f ;/
MOVF 0x0E,W ; P2=word address for the external EEPROM
CALL i2c_wr ; Send the address to be written to the external EEPROM
CALL wr_i2c_string ; and write the byte sequence (actual length is specified in 0x0F)
GOTO TX9000 ; then transmit status bytes


;================================================= ======================
; Signature
;================================================= ======================

ORG 0x03F8

DATA 0x00,'R','e','d','s','t','a','r'

;================================================= ======================
; Identifier
;================================================= ======================

__idlocs 0x4417 ; Version number 441G

;================================================= ======================
; Fuses
;================================================= ====================== ; Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 ; CP CP CP CP CP CP CP CP CP CP PWRTE WDTE FOSC1 FOSC0
__config 0x0009 ; 00 0000 0000 1001 code protect
; __config 0x3FF9 ; 11 1111 1111 1001 no code protect

;================================================= ======================
; Internal EEPROM
;================================================= ======================

ORG 0x2100

; ATR

DATA 0x00
DATA 0xD6
DATA 0xB6
DATA 0x6C
DATA 0x0E
DATA 0x04
DATA 0x30
DATA 0x54
DATA 0x96
DATA 0x40
DATA 0x01
DATA 0x00
DATA 0x11
DATA 0xF7
DATA 0x3B

;Instruction table for C1 (SECA) class byte

DATA 0x0A
DATA 0x0E
DATA 0x16
DATA 0x12
DATA 0x34
DATA 0x32
DATA 0x22
DATA 0x30
DATA 0x21
DATA 0x3A
DATA 0x3C
DATA 0x40
DATA 0x1A
DATA 0x5A

; C1 5A table

ORG 0x2130

DATA 0x18 ; (P2+1) for P1=0
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00
DATA 0x00

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

END

; Version 44.2G
; 2000, November 26






;
; 24C16 DATA
;

LIST P=EEPROM8, F=INHX8M
errorlevel 0,-220

;************************************************* *************
; PAGE 0-1 ANSWER TO C1 INSTRUCTIONS 0E,16,12,32,1A,0A
;************************************************* *************

ORG 0x000

; 0000-0007
; Answer to 0e (smartcard serial number)
DATA 0x00,0x03,0x00,0x00,0x00,0xCA,0x13,0x66

; 0008-000E
; Answer to 16 (number of providers):
; 00 00 nn nn 00 00 FF
; nn nn : 1 bit per provider
DATA 0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF ; <=== UPDATE

ORG 0x010

; 0010-0189
; Answers to 12 (ident):
; ii ii bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
; 00 xx xx xx zz zz
; ii ii : provider channel
; bb..bb : provider name
; xx..xx : smartcard address
; zz zz : termination date (7 bits year since 1990 + 4 bits month + 5 bits day)

DATA 0x00,0x00,'S','E','C','A',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF

DATA 0x00,0x10,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '
DATA 0x00,0x00,0x00,0x00,0xFF,0xFF ; Id: 00 00, PPUA: 00 00 00, Date: FF FF


; 0190-0198
; Reserved for remote update
DATA 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

; 0199-01A5
; Answer to 32 (startup)
DATA 0xB2,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x04

; 01A6-01BA
; Answer to 1a (key index selection)
DATA 0xFF,0xFF,0x0E,0x4C,0x00,0xF0,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

ORG 0x1BB

; 01BB-01FF
; Answer to 0a (operating system version)
DATA 0x61,0x19,0xAD,0xCA,0x15,0x2F,0x10,0x03,0x00,0x00
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
DATA '(','C',')','C','A','N','A','L','+'
DATA '1','9','9','4','/','9','5','/','9','6'
DATA ' ','N','u','m','4','0'
DATA 0x00

;************************************************* *************
; PAGE 2 PROVIDER BITMAP PACKAGE
;************************************************* *************

ORG 0x200

; 0200-027F
; PBM
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ; SECA
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;
DATA 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;

;************************************************* *************
; PAGE 3 SECA TABLE 2
;************************************************* *************

ORG 0x300

; 0300-03FF
; SECA Table 2
DATA 0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8
DATA 0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80
DATA 0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25
DATA 0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e
DATA 0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61
DATA 0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46
DATA 0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03
DATA 0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb
DATA 0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b
DATA 0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6
DATA 0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53
DATA 0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d
DATA 0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f
DATA 0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d
DATA 0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc
DATA 0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78
DATA 0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13
DATA 0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e
DATA 0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa
DATA 0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a
DATA 0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02
DATA 0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7
DATA 0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b
DATA 0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca
DATA 0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60
DATA 0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4
DATA 0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5
DATA 0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8
DATA 0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a
DATA 0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3
DATA 0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe
DATA 0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d

;************************************************* *************
; PAGE 4-7 PROVIDER KEYS
;************************************************* *************

ORG 0x400

; Entity 0
; SECA
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 1
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 2
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 3
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 4
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 5
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 6
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 7
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 8
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity 9
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

; Entity f
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 00/08
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 01/09
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 02/0a
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 03/0b
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 04/0c
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 05/0d
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 06/0e
DATA 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; key 07/0f

END


ps copy/paste vanuit kladbok is niet helemaal handig gelukt :D
suc6 ermee

dreeke
12-07-2002, 17:45
Maakt niet uit, het is toch al voldoende voor de nodige uurtjes puzzelplezier....

Dreeke :)

Kcplus
14-07-2002, 21:58
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 :D .

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

We zoeken nog even verder ;)

Kcplus
22-07-2002, 00:47
De aanhouder wint dus toch...........

Kcplus
22-07-2002, 00:54
De aanhouder wint dus toch........... :D

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 :( ).

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 ;) ............