	LIST FIXED,C=120,F=INHX8M,N=89,P=PIC16C73,R=DEC,T=OFF,W=0,X=OFF

	ERRORLEVEL -305

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                            ;
; TEA16 - Tiny Encryption Algorithm                   Written by Andy Warren ;
; Version 0.2                                         9:30 pm, 20 April 1998 ;
;                                                                            ;
; (C) Fast Forward Engineering 1998                                          ;
; All Rights Reserved                                                        ;
;                                                                            ;
; TEA was developed by David Wheeler and Roger Needham at the Computer       ;
; Laboratory of Cambridge University.                                        ;
;                                                                            ;
; Written for the Microchip Technology PIC16C73 microcontroller (although    ;
; it'll run on any of the PIC16 devices with at least 37 bytes of RAM).      ;
;                                                                            ;
; At 20 MHz, these routines will encrypt or decrypt about 6K bytes per       ;
; second.                                                                    ;
;                                                                            ;
; This program must be assembled with Microchip's MPASM assembler, version   ;
; 1.30.00 or above.                                                          ;
;                                                                            ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	CBLOCK	020H

	K03		;Most-significant byte of the key.
	K02		;
	K01		;
	K00		;
			;
	K13		;
	K12		;
	K11		;
	K10		;
			;
	K23		;
	K22		;
	K21		;
	K20		;
			;
	K33		;
	K32		;
	K31		;
	K30		;Least-significant byte of the key.

	SUM3		;MSB of SUM.
	SUM2		;
	SUM1		;
	SUM0		;LSB of SUM.

	Y3		;MSB of Y.
	Y2		;
	Y1		;
	Y0		;LSB of Y.

	Z3		;MSB of Z.
	Z2		;
	Z1		;
	Z0		;LSB of Z.

	L3		;MSB of L, a temporary variable.
	L2		;
	L1		;
	L0		;LSB of L.

	C3		;MSB of C, another temporary variable.
	C2		;
	C1		;2nd-LSB of C.

	R3		;MSB of R, another temporary variable.
	R2		;
	R1		;
	R0		;LSB of R.

	COUNT		;Number-of-rounds counter.

	ENDC

;
; MAIN
;

	ORG	0

START:

	MOVLW	0	;KEY = 0000 0000 0000 0000.
	MOVWF	K03	;
	MOVLW	0	;
	MOVWF	K02	;
	MOVLW	0	;
	MOVWF	K01	;
	MOVLW	0	;
	MOVWF	K00	;
	MOVLW	0	;
	MOVWF	K13	;
	MOVLW	0	;
	MOVWF	K12	;
	MOVLW	0	;
	MOVWF	K11	;
	MOVLW	0	;
	MOVWF	K10	;
	MOVLW	0	;
	MOVWF	K23	;
	MOVLW	0	;
	MOVWF	K22	;
	MOVLW	0	;
	MOVWF	K21	;
	MOVLW	0	;
	MOVWF	K20	;
	MOVLW	0	;
	MOVWF	K33	;
	MOVLW	0	;
	MOVWF	K32	;
	MOVLW	0	;
	MOVWF	K31	;
	MOVLW	0	;
	MOVWF	K30	;

	MOVLW	0	;PLAINTEXT = 0000 0000.
	MOVWF	Y3	;
	MOVLW	0	;
	MOVWF	Y2	;
	MOVLW	0	;
	MOVWF	Y1	;
	MOVLW	0	;
	MOVWF	Y0	;
	MOVLW	0	;
	MOVWF	Z3	;
	MOVLW	0	;
	MOVWF	Z2	;
	MOVLW	0	;
	MOVWF	Z1	;
	MOVLW	0	;
	MOVWF	Z0	;

; AT THIS POINT, Y3-Z0 CONTAIN THE PLAINTEXT.

	CALL	ENCODE	;ENCODE IT.

; AT THIS POINT, Y3-Z0 CONTAIN THE CIPHERTEXT.

	CALL	DECODE	;DECODE IT.

; AT THIS POINT, Y3-Z0 CONTAIN THE PLAINTEXT AGAIN.
	NOP

STOP:

	GOTO	STOP

;
; Encode Routine
;
; Routine, written in the C language, for encoding with key k[0] - k[3].
; Data in v[0] and v[1].
;
; void code(long* v, long* k)
; {
;     unsigned long y=v[0],z=v[1], sum=0,   /* set up */
;     delta=0x9e3779b9, n=32 ;             /* a key schedule constant */
;
;     while (n-- > 0)
;     {                       /* basic cycle start */
;         sum += delta ;
;
;         y += (z<<4)+k[0] ^ z+sum ^ (z>>5)+k[1] ;
;         z += (y<<4)+k[2] ^ y+sum ^ (y>>5)+k[3] ;   /* end cycle */
;     }
;
;     v[0]=y ; v[1]=z ;
; }
;

ENCODE:

	CLRF	SUM3		;SUM = 0.
	CLRF	SUM2		;
	CLRF	SUM1		;
	CLRF	SUM0		;

	MOVLW	32		;N = 32.
	MOVWF	COUNT		;

ELOOP:

	MOVLW	0B9H		;SUM += 0x9E3779B9.
	ADDWF	SUM0		;
				;
	MOVLW	079H		;
	SKPNC			;
	MOVLW	07AH		;
	ADDWF	SUM1		;
				;
	MOVLW	037H		;
	SKPNC			;
	MOVLW	038H		;
	ADDWF	SUM2		;
				;
	MOVLW	09EH		;
	SKPNC			;
	MOVLW	09FH		;
	ADDWF	SUM3		;

; y += (z<<4)+k[0] ^ z+sum ^ (z>>5)+k[1]

	CALL	ZK01SUB		;L = (Z<<4)+K[0] ^ Z+SUM ^ (Z>>5)+K[1]

	MOVF	L0,W		;Y += L.
	ADDWF	Y0		;
				;
	MOVF	L1,W		;
	SKPNC			;
	INCFSZ	L1,W		;
	ADDWF	Y1		;
				;
	MOVF	L2,W		;
	SKPNC			;
	INCFSZ	L2,W		;
	ADDWF	Y2		;
				;
	MOVF	L3,W		;
	SKPNC			;
	INCFSZ	L3,W		;
	ADDWF	Y3		;

; z += (y<<4)+k[2] ^ y+sum ^ (y>>5)+k[3]

	CALL	YK23SUB		;L = (Y<<4)+K[2] ^ Y+SUM ^ (Y>>5)+K[3]

	MOVF	L0,W		;Z += L.
	ADDWF	Z0		;
				;
	MOVF	L1,W		;
	SKPNC			;
	INCFSZ	L1,W		;
	ADDWF	Z1		;
				;
	MOVF	L2,W		;
	SKPNC			;
	INCFSZ	L2,W		;
	ADDWF	Z2		;
				;
	MOVF	L3,W		;
	SKPNC			;
	INCFSZ	L3,W		;
	ADDWF	Z3		;

	DECFSZ	COUNT		;DONE ALL 32 ROUNDS?
	GOTO	ELOOP		;IF NOT, LOOP BACK AND DO ANOTHER ONE.

	RETURN			;OTHERWISE, RETURN WITH CIPHERTEXT IN
				;Y3 (MSB) THROUGH Z0 (LSB).

;
; Decode Routine
;
; void decode(long* v,long* k)
; {
;     unsigned long n=32, sum, y=v[0], z=v[1],
;     delta=0x9e3779b9 ;
;
;     sum=delta<<5 ;
;                        /* start cycle */
;     while (n-- > 0)
;     {
;         z -= (y<<4)+k[2] ^ y+sum ^ (y>>5)+k[3] ;
;         y -= (z<<4)+k[0] ^ z+sum ^ (z>>5)+k[1] ;
;
;         sum -= delta ;
;     }
;                        /* end cycle */
;     v[0] = y ; v[1] = z ;
; }
;

DECODE:

	MOVLW	0C6H		;SUM = 0x9E3779B9 << 5.
	MOVWF	SUM3		;
	MOVLW	0EFH		;
	MOVWF	SUM2		;
	MOVLW	037H		;
	MOVWF	SUM1		;
	MOVLW	020H		;
	MOVWF	SUM0		;

	MOVLW	32		;N = 32.
	MOVWF	COUNT		;

	GOTO	SKIPSUM		;JUMP INTO THE LOOP.

DLOOP:

	MOVLW	0B9H		;SUM -= 0x9E3779B9.
	SUBWF	SUM0		;
				;
	MOVLW	079H		;
	SKPC			;
	MOVLW	07AH		;
	SUBWF	SUM1		;
				;
	MOVLW	037H		;
	SKPC			;
	MOVLW	038H		;
	SUBWF	SUM2		;
				;
	MOVLW	09EH		;
	SKPC			;
	MOVLW	09FH		;
	SUBWF	SUM3		;

; z -= (y<<4)+k[2] ^ y+sum ^ (y>>5)+k[3]

SKIPSUM:

	CALL	YK23SUB		;L = (Y<<4)+K[2] ^ Y+SUM ^ (Y>>5)+K[3]

	MOVF	L0,W		;Z -= L.
	SUBWF	Z0		;
				;
	MOVF	L1,W		;
	SKPC			;
	INCFSZ	L1,W		;
	SUBWF	Z1		;
				;
	MOVF	L2,W		;
	SKPC			;
	INCFSZ	L2,W		;
	SUBWF	Z2		;
				;
	MOVF	L3,W		;
	SKPC			;
	INCFSZ	L3,W		;
	SUBWF	Z3		;

; y -= (z<<4)+k[0] ^ z+sum ^ (z>>5)+k[1]

	CALL	ZK01SUB		;L = (Z<<4)+K[0] ^ Z+SUM ^ (Z>>5)+K[1]

	MOVF	L0,W		;Y -= L.
	SUBWF	Y0		;
				;
	MOVF	L1,W		;
	SKPC			;
	INCFSZ	L1,W		;
	SUBWF	Y1		;
				;
	MOVF	L2,W		;
	SKPC			;
	INCFSZ	L2,W		;
	SUBWF	Y2		;
				;
	MOVF	L3,W		;
	SKPC			;
	INCFSZ	L3,W		;
	SUBWF	Y3		;

	DECFSZ	COUNT		;HAVE WE DONE ALL 32 ROUNDS?
	GOTO	DLOOP		;IF NOT, LOOP BACK AND DO ANOTHER.

	RETURN			;OTHERWISE, RETURN WITH PLAINTEXT IN
				;Y3 (MSB) THROUGH Z0 (LSB).
	
;
; SUBROUTINES COMMON TO "ENCODE" AND "DECODE".
;

ZK01SUB:

	SWAPF	Z3,W		;L = Z << 4.
	ANDLW	11110000B	;
	MOVWF	L3		;
	SWAPF	Z2,W		;
	ANDLW	00001111B	;
	IORWF	L3		;
				;
	SWAPF	Z2,W		;
	ANDLW	11110000B	;
	MOVWF	L2		;
	SWAPF	Z1,W		;
	ANDLW	00001111B	;
	IORWF	L2		;
				;
	SWAPF	Z1,W		;
	ANDLW	11110000B	;
	MOVWF	L1		;
	SWAPF	Z0,W		;
	ANDLW	00001111B	;
	IORWF	L1		;
				;
	SWAPF	Z0,W		;
	ANDLW	11110000B	;
	MOVWF	L0		;

	SWAPF	Z3,W		;R = (Z >> 5).
	MOVWF	R3		;
	RRF	R3		;
	MOVLW	00000111B	;
	ANDWF	R3		;
				;
	RRF	L3,W		;
	MOVWF	R2		;
				;
	RRF	L2,W		;
	MOVWF	R1		;
				;
	RRF	L1,W		;
	MOVWF	R0		;

	MOVF	K00,W		;L += K[0].
	ADDWF	L0		;
				;
	MOVF	K01,W		;
	SKPNC			;
	INCFSZ	K01,W		;
	ADDWF	L1		;
				;
	MOVF	K02,W		;
	SKPNC			;
	INCFSZ	K02,W		;
	ADDWF	L2		;
				;
	MOVF	K03,W		;
	SKPNC			;
	INCFSZ	K03,W		;
	ADDWF	L3		;

	MOVF	K10,W		;R += K[1].
	ADDWF	R0		;
				;
	MOVF	K11,W		;
	SKPNC			;
	INCFSZ	K11,W		;
	ADDWF	R1		;
				;
	MOVF	K12,W		;
	SKPNC			;
	INCFSZ	K12,W		;
	ADDWF	R2		;
				;
	MOVF	K13,W		;
	SKPNC			;
	INCFSZ	K13,W		;
	ADDWF	R3		;

	MOVF	Z3,W		;SETUP TO CALCULATE L = (Z + SUM) ^ R ^ L.
	MOVWF	C3		;
	MOVF	Z2,W		;
	MOVWF	C2		;
	MOVF	Z1,W		;
	MOVWF	C1		;
	MOVF	Z0,W		;

	GOTO	ADDANDXOR	;GO CALCULATE IT AND RETURN.

YK23SUB:

	SWAPF	Y3,W		;L = Y << 4.
	ANDLW	11110000B	;
	MOVWF	L3		;
	SWAPF	Y2,W		;
	ANDLW	00001111B	;
	IORWF	L3		;
				;
	SWAPF	Y2,W		;
	ANDLW	11110000B	;
	MOVWF	L2		;
	SWAPF	Y1,W		;
	ANDLW	00001111B	;
	IORWF	L2		;
				;
	SWAPF	Y1,W		;
	ANDLW	11110000B	;
	MOVWF	L1		;
	SWAPF	Y0,W		;
	ANDLW	00001111B	;
	IORWF	L1		;
				;
	SWAPF	Y0,W		;
	ANDLW	11110000B	;
	MOVWF	L0		;

	SWAPF	Y3,W		;R = (Y >> 5).
	MOVWF	R3		;
	RRF	R3		;
	MOVLW	00000111B	;
	ANDWF	R3		;
				;
	RRF	L3,W		;
	MOVWF	R2		;
				;
	RRF	L2,W		;
	MOVWF	R1		;
				;
	RRF	L1,W		;
	MOVWF	R0		;

	MOVF	K20,W		;L += K[2].
	ADDWF	L0		;
				;
	MOVF	K21,W		;
	SKPNC			;
	INCFSZ	K21,W		;
	ADDWF	L1		;
				;
	MOVF	K22,W		;
	SKPNC			;
	INCFSZ	K22,W		;
	ADDWF	L2		;
				;
	MOVF	K23,W		;
	SKPNC			;
	INCFSZ	K23,W		;
	ADDWF	L3		;

	MOVF	K30,W		;R += K[3].
	ADDWF	R0		;
				;
	MOVF	K31,W		;
	SKPNC			;
	INCFSZ	K31,W		;
	ADDWF	R1		;
				;
	MOVF	K32,W		;
	SKPNC			;
	INCFSZ	K32,W		;
	ADDWF	R2		;
				;
	MOVF	K33,W		;
	SKPNC			;
	INCFSZ	K33,W		;
	ADDWF	R3		;

	MOVF	Y3,W		;SETUP TO CALCULATE L = (Y + SUM) ^ R ^ L.
	MOVWF	C3		;
	MOVF	Y2,W		;
	MOVWF	C2		;
	MOVF	Y1,W		;
	MOVWF	C1		;
	MOVF	Y0,W		;
				;
				;FALL THROUGH TO "ADDANDXOR".

;
; ENTER WITH MOST-SIGNIFICANT 3 BYTES OF Y OR Z IN C3-C1, LEAST-SIGNIFICANT
; BYTE IN W.
;

ADDANDXOR:

	ADDWF	SUM0,W		;L = (C + SUM) ^ R ^ L.
	XORWF	R0,W		;
	XORWF	L0		;
				;
	MOVF	SUM1,W		;
	SKPNC			;
	INCFSZ	SUM1,W		;
	ADDWF	C1		;
	MOVF	C1,W		;
	XORWF	R1,W		;
	XORWF	L1		;
				;
	MOVF	SUM2,W		;
	SKPNC			;
	INCFSZ	SUM2,W		;
	ADDWF	C2		;
	MOVF	C2,W		;
	XORWF	R2,W		;
	XORWF	L2		;
				;
	MOVF	SUM3,W		;
	SKPNC			;
	INCFSZ	SUM3,W		;
	ADDWF	C3		;
	MOVF	C3,W		;
	XORWF	R3,W		;
	XORWF	L3		;

	RETURN			;RETURN.
	
	END

