Original PIC assembler
PIC source code of a Skipjack block cipher by Eric Smith (All rights acknowledged). NB: Three files have been combined here and the test cases at the end shortened in order to make a simpler example, but the code is otherwise unchanged.
;-----------------------------------------------------------------------------
; SKIPJACK test program - part of SKIPJACK distribution
; Copyright 1998, 1999 Eric Smith
; $Id: sjtest.asm,v 1.2 1999/05/07 02:07:39 eric Exp $
;
; WARNING: This software may be subject to export controls
;
; http://www.brouhaha.com/~eric/pic/
; http://www.brouhaha.com/~eric/crypto/
;
; SKIPJACK is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License version 2 as published by
; the Free Software Foundation. Note that I am not granting permission to
; redistribute or modify SKIPJACK under the terms of any later version of
; the General Public License.
;
; This program is distributed in the hope that it will be useful (or at least
; amusing), 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 (in the file "COPYING"); if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; This software has been tested using the GPASM assembler:
; http://reality.sgi.com/jamesb/gpasm/
; and the PSIM simulator:
; http://www.brouhaha.com/~eric/pic/psim.html
;
; It may work with Microchip's MPASM assembler, but has not been tested.
;-----------------------------------------------------------------------------
radix dec
; This test program is only intended for use on the PSIM simulator.
#define simulator
; To get cycle counts from PSIM, uncomment the following define
;#define benchmark
;-----------------------------------------------------------------------------
; processor
;-----------------------------------------------------------------------------
processor 16c84
rambase equ 0x0c
rombase equ 0x000
;-----------------------------------------------------------------------------
; register and bit definitions common to all midrange PICs
;-----------------------------------------------------------------------------
w equ 0
f equ 1
indf equ 0x00
tmr0 equ 0x01
pcl equ 0x02
status equ 0x03
fsr equ 0x04
porta equ 0x05
portb equ 0x06
pclath equ 0x0a
optreg equ 0x81
trisa equ 0x85
trisb equ 0x86
; bits in status register
irp equ 7
rp1 equ 6
rp0 equ 5
to equ 4
pd equ 3
z equ 2
dc equ 1
c equ 0
; bits in option register
rbpu equ 7
intedg equ 6
t0cs equ 5
t0se equ 4
psa equ 3
ps2 equ 2
ps1 equ 1
ps0 equ 0
;-----------------------------------------------------------------------------
; ASCII characters
;-----------------------------------------------------------------------------
cr equ 0x0d
lf equ 0x0a
;-----------------------------------------------------------------------------
; macros for special PSIM instructions
;-----------------------------------------------------------------------------
ifdef simulator
output macro ; output a character to simulator console
data 0x00b
endm
endif
ifdef simulator
ifdef benchmark
mark macro ; output cycle count to simulator console
data 0x00c
endm
else
mark macro
endm
endif
endif
halt macro
goto $
endm
;-----------------------------------------------------------------------------
; RAM allocation
;-----------------------------------------------------------------------------
cblock rambase
count
tot_vec
good_enc
bad_enc
good_dec
bad_dec
endc
;-----------------------------------------------------------------------------
; start of ROM
;-----------------------------------------------------------------------------
org rombase
goto reset
nop
nop
nop
goto reset ; we're not using interrupts
;-----------------------------------------------------------------------------
; message table
;-----------------------------------------------------------------------------
message_page equ $>>8
msgtab: addwf PCL
banner equ $-(msgtab+1)
dt cr,lf,"SKIPJACK for PIC",cr,lf
dt "Copyright 1998 Eric Smith"
crlf equ $-(msgtab+1)
dt cr,lf,0
donemsg equ $-(msgtab+1)
dt "Test completed. Total vectors: ",0
encmsg equ $-(msgtab+1)
dt "Encryptions ",0
decmsg equ $-(msgtab+1)
dt "Decryptions ",0
pcntmsg equ $-(msgtab+1)
dt "passed: ",0
fcntmsg equ $-(msgtab+1)
dt ", failed: ",0
passmsg equ $-(msgtab+1)
dt " pass",0
failmsg equ $-(msgtab+1)
dt " FAIL!!! Should be: ",0
keymsg equ $-(msgtab+1)
dt "Key: ",0
plaintextmsg equ $-(msgtab+1)
dt "Plaintext: ", 0
ciphertextmsg equ $-(msgtab+1)
dt "Ciphertext: ", 0
if (msgtab>>8)!=($>>8)
error "messages must reside within a single page"
endif
;-----------------------------------------------------------------------------
; utility functions
;-----------------------------------------------------------------------------
print_key:
movlw keymsg
call msgout
movlw key
movwf fsr
movlw keylen
movwf count
goto outhexram
print_plaintext:
movlw plaintextmsg
goto print_text
print_ciphertext:
movlw ciphertextmsg
print_text:
call msgout
print_block:
movlw text
movwf fsr
movlw blocklen
movwf count
goto outhexram
outhexram:
movf indf,w
call outhb
incf fsr
decfsz count
goto outhr1
return
outhr1: movlw '.'
call xmit
goto outhexram
;-----------------------------------------------------------------------------
; output a byte in hexadecimal
; uses temp
;-----------------------------------------------------------------------------
outhb: movwf temp
outhb1: swapf temp,w
call outhd
movf temp,w
; fall into outhd
;-----------------------------------------------------------------------------
; output a hex digit
;-----------------------------------------------------------------------------
outhd: andlw 0x0f
addlw 0xf6
btfsc status,c
addlw 0x07
addlw 0x3a
; fall into xmit
;-----------------------------------------------------------------------------
; serial transmit character
;-----------------------------------------------------------------------------
xmit: output ; works for simulator only
return
;-----------------------------------------------------------------------------
; message output subroutine
;-----------------------------------------------------------------------------
msgout: movwf temp
movlw message_page
movwf pclath
msglp: movf temp,W
call msgtab
xorlw 0
btfsc status,z
return
call xmit
incf temp
goto msglp
;-----------------------------------------------------------------------------
; initialization code
;-----------------------------------------------------------------------------
reset:
movlw 0xff ; all port pins are inputs (or inactive
tris porta ; open-drain outputs)
tris portb
clrf porta
clrf portb
clrf tot_vec
clrf good_enc
clrf bad_enc
clrf good_dec
clrf bad_dec
movlw banner
call msgout
;-----------------------------------------------------------------------------
; main loop
;-----------------------------------------------------------------------------
main: call init_test_vec
loop: incf tot_vec
movlw key
movwf fsr
call get_test_vec_key
call print_key
movlw crlf
call msgout
movlw text
movwf fsr
call get_test_vec_block
call print_plaintext
movlw crlf
call msgout
mark
call encrypt
mark
call print_ciphertext
movlw text
movwf fsr
call compare_test_vec_block
btfss status,z
goto enc_fail
incf good_enc
movlw passmsg
call msgout
movlw crlf
call msgout
goto do_dec
enc_fail:
incf bad_enc
movlw failmsg
call msgout
call backup_test_vec_block
call get_test_vec_block
call print_block
movlw crlf
call msgout
do_dec:
mark
call decrypt
mark
call print_plaintext
movlw text
movwf fsr
call backup_test_vec_block
call backup_test_vec_block
call compare_test_vec_block
btfss status,z
goto dec_fail
incf good_dec
movlw passmsg
call msgout
movlw crlf
call msgout
goto do_next
dec_fail:
incf bad_dec
movlw failmsg
call msgout
call backup_test_vec_block
call get_test_vec_block
call print_block
movlw crlf
call msgout
do_next:
call skip_test_vec_block
movlw crlf
call msgout
movlw crlf
call msgout
call end_of_test_vec
btfss status,z
goto loop
movlw donemsg
call msgout
movf tot_vec,w
call outhb
movlw crlf
call msgout
movlw encmsg
call msgout
movlw pcntmsg
call msgout
movf good_enc,w
call outhb
movlw fcntmsg
call msgout
movf bad_enc,w
call outhb
movlw crlf
call msgout
movlw decmsg
call msgout
movlw pcntmsg
call msgout
movf good_dec,w
call outhb
movlw fcntmsg
call msgout
movf bad_dec,w
call outhb
movlw crlf
call msgout
halt
;-----------------------------------------------------------------------------
; SKIPJACK for Microchip's midrange PIC processors
; Copyright 1998, 1999 Eric Smith
; $Id: skipjack.inc,v 1.5 1999/05/07 02:07:39 eric Exp $
;
; WARNING: This software may be subject to export controls
;
; http://www.brouhaha.com/~eric/pic/
; http://www.brouhaha.com/~eric/crypto/
;
; SKIPJACK is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License version 2 as published by
; the Free Software Foundation. Note that I am not granting permission to
; redistribute or modify SKIPJACK under the terms of any later version of
; the General Public License.
;
; This program is distributed in the hope that it will be useful (or at least
; amusing), 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 (in the file "COPYING"); if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; This implementation is believed to be compliant with the SKIPJACK
; algorithm as described in "SKIPJACK and KEA Algorithm Specifications"
; Version 2.0 dated 29 May 1998, which is available from the National
; Institute for Standards and Technology:
; http://csrc.nist.gov/encryption/skipjack-kea.htm
;
; This software has been tested using the GPASM assembler:
; http://reality.sgi.com/jamesb/gpasm/
; and the PSIM simulator:
; http://www.brouhaha.com/~eric/pic/psim.html
;
; It may work with Microchip's MPASM assembler, but has not been tested.
;-----------------------------------------------------------------------------
#define has_encrypt
#define has_decrypt
;#define inline_g ; bigger code, but slightly faster
;-----------------------------------------------------------------------------
; constants for SKIPJACK
;-----------------------------------------------------------------------------
; Don't assume that just because keylen, blocklen, and rounds are
; defined as constants, that you can change them arbitrarily and
; expect the code to still work. It's mostly hard-coded.
; In particular, you might be tempted to change the key length to
; something other than ten bytes. As written, the code will actually
; behave in the expected and predictable manner with any key length
; that is even. However, lengths other than ten bytes are not
; compliant with the SKIPJACK specification. Longer lengths can not
; be assumed to be more secure. I suspect that key lengths that are a
; multiple of four are probably very insecure.
keylen equ 10
blocklen equ 8
rounds equ 32
;-----------------------------------------------------------------------------
; RAM allocation
;-----------------------------------------------------------------------------
cblock
key: keylen
text: blocklen ; used for both plaintext and ciphertext
round
temp
endc
;-----------------------------------------------------------------------------
; SKIPJACK encryption
;-----------------------------------------------------------------------------
ifndef no_encrypt
half_g_mac macro
movf indf,w
xorwf text+3,w
call get_f
xorwf text+2
incf fsr ; key length is even, so this will never
; pass the end of the table
movf indf,w
xorwf text+2,w
call get_f
xorwf text+3
incf fsr
movf fsr,w
xorlw key+keylen
movlw key
btfsc status,z
movwf fsr
endm
ifndef inline_g
half_g: half_g_mac
return
endif
encrypt:
movlw f_table>>8
movwf pclath
movlw key
movwf fsr
clrf round
encrypt_loop:
movf text+6,w ; rotate plaintext right 16 bits
movwf temp
movf text+4,w
movwf text+6
movf text+2,w
movwf text+4
movf text+0,w
movwf text+2
movf temp,w
movwf text+0
movf text+7,w
movwf temp
movf text+5,w
movwf text+7
movf text+3,w
movwf text+5
movf text+1,w
movwf text+3
movf temp,w
movwf text+1
btfss round,3
goto encrypt_1
movf text+2,w ; rule b
xorwf text+4
incf round,w
xorwf text+3,w
xorwf text+5
encrypt_1:
ifdef inline_g
half_g_mac
half_g_mac
else
call half_g
call half_g
endif
btfsc round,3
goto encrypt_2
movf text+2,w ; rule a
xorwf text+0
incf round,w
xorwf text+3,w
xorwf text+1
encrypt_2:
incf round
btfss round,5
goto encrypt_loop
return
endif
;-----------------------------------------------------------------------------
; SKIPJACK decryption
;-----------------------------------------------------------------------------
ifndef no_decrypt
half_g_inv_mac macro
movf indf,w
xorwf text+0,w
call get_f
xorwf text+1
decf fsr
movf indf,w
xorwf text+1,w
call get_f
xorwf text+0
decf fsr
movf fsr,w
xorlw key-1
movlw key+keylen-1
btfsc status,z
movwf fsr
endm
ifndef inline_g
half_g_inv:
half_g_inv_mac
return
endif
decrypt:
movlw f_table>>8
movwf pclath
movlw key+((rounds*4-1)%keylen)
movwf fsr
movlw 31
movwf round
decrypt_loop:
movf text+0,w ; rotate plaintext left 16 bits
movwf temp
movf text+2,w
movwf text+0
movf text+4,w
movwf text+2
movf text+6,w
movwf text+4
movf temp,w
movwf text+6
movf text+1,w
movwf temp
movf text+3,w
movwf text+1
movf text+5,w
movwf text+3
movf text+7,w
movwf text+5
movf temp,w
movwf text+7
btfsc round,3
goto decrypt_1
movf text+0,w ; rule a inv
xorwf text+6
incf round,w
xorwf text+1,w
xorwf text+7
decrypt_1:
ifdef inline_g
half_g_inv_mac
half_g_inv_mac
else
call half_g_inv
call half_g_inv
endif
btfss round,3
goto decrypt_2
movf text+0,w ; rule b inv
xorwf text+2
incf round,w
xorwf text+1,w
xorwf text+3
decrypt_2:
decf round
btfss round,7
goto decrypt_loop
return
endif
;-----------------------------------------------------------------------------
; SKIPJACK F table
;-----------------------------------------------------------------------------
; get an entry from the f table
;
; On entry: table index in W. high byte of table address in pclath.
; On return: table value in W.
get_f: movwf pcl
; force table to be aligned to a page boundary
org ($+0xff)&~0xff
f_table:
dt 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4
dt 0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9
dt 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e
dt 0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28
dt 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68
dt 0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53
dt 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19
dt 0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2
dt 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b
dt 0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8
dt 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0
dt 0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90
dt 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69
dt 0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76
dt 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20
dt 0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d
dt 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43
dt 0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18
dt 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa
dt 0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4
dt 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87
dt 0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40
dt 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b
dt 0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5
dt 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0
dt 0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2
dt 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1
dt 0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8
dt 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5
dt 0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac
dt 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3
dt 0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
;-----------------------------------------------------------------------------
; test vectors
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
; SKIP test vectors - part of SKIPJACK distribution
; Copyright 1998, 1999 Eric L. Smith
; $Id: testvec.inc,v 1.3 1999/05/07 02:07:39 eric Exp $
;
; WARNING: This software may be subject to export controls
;
; http://www.brouhaha.com/~eric/pic/
; http://www.brouhaha.com/~eric/crypto/
;
; SKIPJACK is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License version 2 as published by
; the Free Software Foundation. Note that I am not granting permission to
; redistribute or modify SKIPJACK under the terms of any later version of
; the General Public License.
;
; This program is distributed in the hope that it will be useful (or at least
; amusing), 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 (in the file "COPYING"); if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; This software has been tested using the GPASM assembler:
; http://reality.sgi.com/jamesb/gpasm/
; and the PSIM simulator:
; http://www.brouhaha.com/~eric/pic/psim.html
;
; It may work with Microchip's MPASM assembler, but has not been tested.
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
; RAM definitions
;-----------------------------------------------------------------------------
cblock
vec_ptr: 2
endc
;-----------------------------------------------------------------------------
; init_test_vec
;-----------------------------------------------------------------------------
init_test_vec:
movlw test_vec_tab&0xff
movwf vec_ptr
movlw test_vec_tab>>8
movwf vec_ptr+1
return
;-----------------------------------------------------------------------------
; backup_test_vec_block
;-----------------------------------------------------------------------------
backup_test_vec_block:
movlw -blocklen
addwf vec_ptr
btfss status,c
decf vec_ptr+1
return
;-----------------------------------------------------------------------------
; skip_test_vec_block
;-----------------------------------------------------------------------------
skip_test_vec_block:
movlw blocklen
addwf vec_ptr
btfsc status,c
incf vec_ptr+1
return
;-----------------------------------------------------------------------------
; end_of_test_vec
;-----------------------------------------------------------------------------
end_of_test_vec:
movf vec_ptr,w
xorlw test_vec_tab_end&0xff
btfss status,z
return
movf vec_ptr+1,w
xorlw test_vec_tab_end>>8
return
;-----------------------------------------------------------------------------
; get one byte from test vector array, and advance pointer
;-----------------------------------------------------------------------------
get_test_vec_byte:
movf vec_ptr+1,w
movwf pclath
movf vec_ptr,w
incf vec_ptr
btfsc status,z
incf vec_ptr+1
movwf pcl
;-----------------------------------------------------------------------------
; copies keylen bytes of data from the test vector array into the RAM
; pointed to by FSR.
;
; on exit, the test vector pointer is increased by keylen, but FSR is
; unchanged
;
; uses count
;-----------------------------------------------------------------------------
get_test_vec_key:
movlw keylen
movwf count
gtvk0: call get_test_vec_byte
clrf pclath
movwf indf
incf fsr
decfsz count
goto gtvk0
movlw -keylen
addwf fsr
return
;-----------------------------------------------------------------------------
; copies blocklen bytes of data from the test vector array into the RAM
; pointed to by FSR.
;
; on exit, the test vector pointer is increased by blocklen, but FSR is
; unchanged
;
; uses count
;-----------------------------------------------------------------------------
get_test_vec_block:
movlw blocklen
movwf count
gtvb0: call get_test_vec_byte
clrf pclath
movwf indf
incf fsr
decfsz count
goto gtvb0
movlw -blocklen
addwf fsr
return
;-----------------------------------------------------------------------------
; compares blocklen bytes of data from the test vector array to the RAM
; pointed to by FSR.
;
; on exit, the test vector pointer is increased by blocklen, but FSR is
; unchanged. The zero flag will be set if the test vector is equal to the
; RAM value.
;
; uses count, temp
;-----------------------------------------------------------------------------
compare_test_vec_block:
movlw blocklen
movwf count
clrf temp
ctvb0: call get_test_vec_byte
clrf pclath
xorwf indf,w
iorwf temp
incf fsr
decfsz count
goto ctvb0
movlw -blocklen
addwf fsr
movf temp ; set Z flag appropriately
return
;-----------------------------------------------------------------------------
; and finally, the actual test vectors
;-----------------------------------------------------------------------------
test_vec_tab:
; This vector is from the SKIPJACK protocol specification:
dt 0x00,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11 ; key
dt 0x33,0x22,0x11,0x00,0xdd,0xcc,0xbb,0xaa ; plaintext
dt 0x25,0x87,0xca,0xe2,0x7a,0x12,0xd3,0x00 ; ciphertext
...further values omitted here to shorten example
test_vec_tab_end:
end