; ============================================================ ; crypto1_lfsr.S - Crypto-1 functions (LFSR) ; ; Copyright (C) 2010-2013, Tomas Pecina ; ; This file is part of PICCE, an open source PICC emulator. ; ; PICCE is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; PICCE is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ; #include "picce.inc" ; ============================================================ ; Data ; ; Register variables: ; crypto1_lfsr0 to 5 - LFSR state ; ; ============================================================ ; crypto1lshift/crypto1lshiftc - shift LFSR ; (crypto1lshiftc: reset T) ; ; input: crypto1_lfsr ; T - input bit ; output: crypto1_lfsr shifted ; uses: WL, WH ; .global crypto1lshiftc .global crypto1lshift crypto1lshiftc: clt crypto1lshift: movw WX, AX clr AH bld AH, 0 ldi AL, 0b00100001 ; bits 0, 5 and AL, crypto1_lfsr0 eor AH, AL ldi AL, 0b11010110 ; bits 9, 10, 12, 14, 15 and AL, crypto1_lfsr1 eor AH, AL ldi AL, 0b00001010 ; bits 17, 19 and AL, crypto1_lfsr2 eor AH, AL ldi AL, 0b00101011 ; bits 24, 25, 27, 29 and AL, crypto1_lfsr3 eor AH, AL ldi AL, 0b10001000 ; bits 35, 39 and AL, crypto1_lfsr4 eor AH, AL ldi AL, 0b00001110 ; bits 41, 42, 43 and AL, crypto1_lfsr5 eor AH, AL mov AL, AH swap AL eor AL, AH adi AL, 0x41 ori AL, 0x7c adi AL, 0x02 rol AL .irp iter, 5, 4, 3, 2, 1, 0 ror crypto1_lfsr0 + \iter .endr movw AX, WX ret ; ============================================================ ; crypto1f - calculate f of LFSR ; ; input: crypto1_lfsr ; output: T - f ; uses: VL, WL, WH ; .global crypto1f crypto1f: pushw ZX clr WH clr VL mov WL, crypto1_lfsr5 lsr WL ldiw ZX, crypto1fb addw ZX, WX lpm WL, Z ror WL rol VL mov WL, crypto1_lfsr4 lsr WL ldiw ZX, crypto1fa addw ZX, WX lpm WL, Z ror WL rol VL mov WL, crypto1_lfsr3 lsr WL ldiw ZX, crypto1fb addw ZX, WX lpm WL, Z ror WL rol VL mov WL, crypto1_lfsr2 lsr WL ldiw ZX, crypto1fb addw ZX, WX lpm WL, Z ror WL rol VL mov WL, crypto1_lfsr1 lsr WL ldiw ZX, crypto1fa addw ZX, WX lpm WL, Z ror WL rol VL mov WL, VL ldiw ZX, crypto1fc addw ZX, WX lpm WL, Z bst WL, 0 popw ZX ret .const crypto1fa: .byte 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 .byte 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 .byte 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 .byte 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 .byte 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0 .byte 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 .byte 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0 .byte 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 crypto1fb: .byte 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 .byte 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1 .byte 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 .byte 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1 .byte 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 .byte 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1 .byte 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 .byte 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1 crypto1fc: .byte 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 .byte 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1 .previous ; ============================================================ ; crypto1enc - encrypt bytestream ; (crypto1encc: reset CL) ; input: X - pointer to bytestream ; Y - number of complete bytes to encrypt ; CL - number of bits in the incomplete 1st byte ; Z - pointer to bitstream ; output: bitstream ; Y - number of bits ; uses: AL, AH, CL, CH, DL, DH, EL, EH, VL, WL, WH, X, Z, T ; ; Note: Incomplete byte is shifted to MSB. ; .global crypto1encc .global crypto1enc crypto1encc: clr CL crypto1enc: incw YX movw EX, YX clrw YX clr CH ldi DH, 0x80 tst CL breq 10f ; incomplete first byte ld DL, X+ mov AL, CL 11: lsr DL inc AL cpi AL, 8 brne 11b rjmp 1f ; incomplete byte's parity is irrelevant, but we want it deterministic ; complete first byte 10: decw EX brne 14f cpi DH, 0x80 breq 12f decw YX clc 13: ror DH brcc 13b rjmp 17f 14: ld DL, X+ ldi CL, 8 1: ser AH 15: eor AH, DL rcall crypto1f bld CH, 0 eor DL, CH rcall crypto1lshiftc ror DL rcall 16f dec CL brne 15b rcall crypto1f bld CH, 0 eor AH, CH ror AH rcall 16f rjmp 10b 16: ror DH brcc 18f 17: st Z+, DH ldi DH, 0x80 18: incw YX 12: ret ; ============================================================ ; crypto1dec/crypto1decc - decrypt bitstream (checking parity & CRC_A) ; (crypto1decc: reset CH) ; input: Z - pointer to bitstream ; Y - number of bits ; X - pointer to bytestream ; CH - nonzero value suppresses CRC check ; output: bytestream ; Y - number of bytes decrypted ; (=0 parity or CRC error) ; uses: AL, AH, CL, CH, DL, DH, EL, EH, VL, WL, WH, X, Z, T ; .global crypto1decc .global crypto1dec crypto1decc: clr CH crypto1dec: tst CH brne 7f call crcainit 7: movw DX, YX clrw YX clr EL clr VH 3: ser AH ldi CL, 8 sbiwf DX, 9 brcc 8f 4: clrw YX ret 8: rcall 19f 9: rcall crypto1f bld VH, 0 eor AL, VH eor AH, AL ror AL ror EH rcall crypto1lshiftc dec CL brne 8b rcall 19f rcall crypto1f bld VH, 0 eor AL, VH eor AH, AL lsr AL ror AH brcs 4b incw YX st X+, EH tst CH brne 6f push AL mov AL, EH call crcaupd pop AL 6: mov AH, DH or AH, DL brne 3b tst CH brne 5f ldsw AX, crc16 or AL, AH breq 5f clrw YX 5: ret 19: tst EL brne 20f ld AL, Z+ ldi EL, 8 20: dec EL ret ; ============================================================ ; crypto1encfr/crypto1decfr - encrypt/decrypt incomplete byte, in situ ; input: AL - input byte ; CL - number of bits ; output: AL - output byte ; uses: AH, BH, CL, VL, WL, WH, T ; .global crypto1encfr .global crypto1decfr crypto1encfr: crypto1decfr: ldi BH, 0x80 clr AH 21: rcall crypto1f bld AH, 0 eor AL, AH ror AL ror BH rcall crypto1lshiftc dec CL brne 21b clc 22: ror BH brcc 22b mov AL, BH ret .end