*
*  Copyright R.M.A.Lucock 1991
*

   CSECT data,1,,0

ML_CNT DS.L 1
LHP    DS.L 1
RHP    DS.L 1

   INCLUDE adesdat.inc

   CSECT text,0,,0
   XDEF _encrypt
   XREF _KSB

*
* Function to DES encrypt a block of 64 bits, given the key bits in
* an external array _KSB. The input block has the bits numbered in
* reverse order to the usual convention for programming. During the
* initial permutation, DES 'bit 1' is mapped to standard 'bit' 1
* of the lower word. The final permutation reverses this so that
* everything looks OK to DES on exiting this routine.
*


*
* Passes one parm - the address of an 8 byte array
*


_encrypt equ *

   link a5,#0

* Save some registers

   movem.l d2-d7/a2-a4/a6,-(a7)

* do initial perm

   movea.l 8(a5),a0        ; pointer to initial data
   movea.l #fp_tab,a1      ; final perm tab (used in the 'active' mode)
   clr.l d0                ; index into fp_tab
   moveq.l #1,d1           ; counter for loop over input data words
   clr.l d5                ; (temp buffer for low order bits)
   clr.l d6                ; (temp buffer for hi order bits)

ip_lw_loop:

   move.l (a0)+,d2         ; set up input data word
   moveq.l #15,d3          ; set up counter for loop over data bits
                           ; (we do two bits per loop)

ip_bit_loop:

   asl.l #1,d2
   bcc ip_odd_bit
   move.l 0(a1,d0),d4
   or.l d4,d6

ip_odd_bit:

   asl.l #1,d2
   bcc ip_no_bit
   move.l 4(a1,d0),d4
   or.l d4,d5

ip_no_bit:

   addq.l #8,d0
   dbra d3,ip_bit_loop
   dbra d1,ip_lw_loop


*
* Now do 16 iterations
*

   moveq.l #15,d7           ; iteration-loop counter
   movea.l #_KSB,a6         ; pointer to key data

*
* expand the right hand side of the block (upper long word) from 32
* bits to 48, using the E-bit table.
* We loop from upper bits to lower bits so that we can use the loop
* counter for indexing
*

   move.l d6,d2

main_iter:

   clr.l d3
   clr.l d4

   btst.l #0,d2
   beq eblab_00
   bset.l #1,d3
   bset.l #15,d4
eblab_00:
   btst.l #1,d2
   beq eblab_01
   bset.l #2,d3
eblab_01:
   btst.l #2,d2
   beq eblab_02
   bset.l #3,d3
eblab_02:
   btst.l #3,d2
   beq eblab_03
   bset.l #4,d3
   bset.l #6,d3
eblab_03:
   btst.l #4,d2
   beq eblab_04
   bset.l #5,d3
   bset.l #7,d3
eblab_04:
   btst.l #5,d2
   beq eblab_05
   bset.l #8,d3
eblab_05:
   btst.l #6,d2
   beq eblab_06
   bset.l #9,d3
eblab_06:
   btst.l #7,d2
   beq eblab_07
   bset.l #10,d3
   bset.l #12,d3
eblab_07:
   btst.l #8,d2
   beq eblab_08
   bset.l #11,d3
   bset.l #13,d3
eblab_08:
   btst.l #9,d2
   beq eblab_09
   bset.l #14,d3
eblab_09:
   btst.l #10,d2
   beq eblab_10
   bset.l #15,d3
eblab_10:
   btst.l #11,d2
   beq eblab_11
   bset.l #16,d3
   bset.l #18,d3
eblab_11:
   btst.l #12,d2
   beq eblab_12
   bset.l #17,d3
   bset.l #19,d3
eblab_12:
   btst.l #13,d2
   beq eblab_13
   bset.l #20,d3
eblab_13:
   btst.l #14,d2
   beq eblab_14
   bset.l #21,d3
eblab_14:
   btst.l #15,d2
   beq eblab_15
   bset.l #22,d3
   bset.l #24,d3
eblab_15:
   btst.l #16,d2
   beq eblab_16
   bset.l #23,d3
   bset.l #25,d3
eblab_16:
   btst.l #17,d2
   beq eblab_17
   bset.l #26,d3
eblab_17:
   btst.l #18,d2
   beq eblab_18
   bset.l #27,d3
eblab_18:
   btst.l #19,d2
   beq eblab_19
   bset.l #28,d3
   bset.l #30,d3
eblab_19:
   btst.l #20,d2
   beq eblab_20
   bset.l #29,d3
   bset.l #31,d3
eblab_20:
   btst.l #21,d2
   beq eblab_21
   bset.l #0,d4
eblab_21:
   btst.l #22,d2
   beq eblab_22
   bset.l #1,d4
eblab_22:
   btst.l #23,d2
   beq eblab_23
   bset.l #2,d4
   bset.l #4,d4
eblab_23:
   btst.l #24,d2
   beq eblab_24
   bset.l #3,d4
   bset.l #5,d4
eblab_24:
   btst.l #25,d2
   beq eblab_25
   bset.l #6,d4
eblab_25:
   btst.l #26,d2
   beq eblab_26
   bset.l #7,d4
eblab_26:
   btst.l #27,d2
   beq eblab_27
   bset.l #8,d4
   bset.l #10,d4
eblab_27:
   btst.l #28,d2
   beq eblab_28
   bset.l #9,d4
   bset.l #11,d4
eblab_28:
   btst.l #29,d2
   beq eblab_29
   bset.l #12,d4
eblab_29:
   btst.l #30,d2
   beq eblab_30
   bset.l #13,d4
eblab_30:
   btst.l #31,d2
   beq eblab_31
   bset.l #0,d3
   bset.l #14,d4
eblab_31:

*
* Now exclusive-or the results with the key for this iteration
*

   move.l (a6)+,d0
   eor.l d0,d3
   move.l (a6)+,d0
   eor.l d0,d4

*
* We now have 48 bits, in 8 groups of six bits. We use each group
* to index into relevant the s-box table to pick up a four bit number
* which will replace the six bit number. We label the groups 1-8.
*

   clr.l d1
   movea.l #sbox_tab,a0
   moveq.l #4,d0

sbit_loop_1:

   move.l d3,d2
   lsr.l #6,d3
   and.l #63,d2
   asl.l #2,d2
   or.l 0(a0,d2),d1
   add.l #256,a0
   dbra d0,sbit_loop_1

*
* We now have the lower two bits of group 6 in d3, and the upper four
* bits in d4.
*
   asl.l #2,d4
   or.l d4,d3
   moveq.l #2,d0

sbit_loop_2:

   move.l d3,d2
   asr.l #6,d3
   and.l #63,d2
   asl.l #2,d2
   or.l 0(a0,d2),d1
   add.l #256,a0
   dbra d0,sbit_loop_2

*
* the result is in register d1. We permute it using the P table. This is
* a simple 32-bit to 32-bit perm.
*

   clr.l d2             ; result register

   btst.l #15,d1
   beq pplab_00
   bset.l #0,d2
pplab_00:
   btst.l #6,d1
   beq pplab_01
   bset.l #1,d2
pplab_01:
   btst.l #19,d1
   beq pplab_02
   bset.l #2,d2
pplab_02:
   btst.l #20,d1
   beq pplab_03
   bset.l #3,d2
pplab_03:
   btst.l #28,d1
   beq pplab_04
   bset.l #4,d2
pplab_04:
   btst.l #11,d1
   beq pplab_05
   bset.l #5,d2
pplab_05:
   btst.l #27,d1
   beq pplab_06
   bset.l #6,d2
pplab_06:
   btst.l #16,d1
   beq pplab_07
   bset.l #7,d2
pplab_07:
   btst.l #0,d1
   beq pplab_08
   bset.l #8,d2
pplab_08:
   btst.l #14,d1
   beq pplab_09
   bset.l #9,d2
pplab_09:
   btst.l #22,d1
   beq pplab_10
   bset.l #10,d2
pplab_10:
   btst.l #25,d1
   beq pplab_11
   bset.l #11,d2
pplab_11:
   btst.l #4,d1
   beq pplab_12
   bset.l #12,d2
pplab_12:
   btst.l #17,d1
   beq pplab_13
   bset.l #13,d2
pplab_13:
   btst.l #30,d1
   beq pplab_14
   bset.l #14,d2
pplab_14:
   btst.l #9,d1
   beq pplab_15
   bset.l #15,d2
pplab_15:
   btst.l #1,d1
   beq pplab_16
   bset.l #16,d2
pplab_16:
   btst.l #7,d1
   beq pplab_17
   bset.l #17,d2
pplab_17:
   btst.l #23,d1
   beq pplab_18
   bset.l #18,d2
pplab_18:
   btst.l #13,d1
   beq pplab_19
   bset.l #19,d2
pplab_19:
   btst.l #31,d1
   beq pplab_20
   bset.l #20,d2
pplab_20:
   btst.l #26,d1
   beq pplab_21
   bset.l #21,d2
pplab_21:
   btst.l #2,d1
   beq pplab_22
   bset.l #22,d2
pplab_22:
   btst.l #8,d1
   beq pplab_23
   bset.l #23,d2
pplab_23:
   btst.l #18,d1
   beq pplab_24
   bset.l #24,d2
pplab_24:
   btst.l #12,d1
   beq pplab_25
   bset.l #25,d2
pplab_25:
   btst.l #29,d1
   beq pplab_26
   bset.l #26,d2
pplab_26:
   btst.l #5,d1
   beq pplab_27
   bset.l #27,d2
pplab_27:
   btst.l #21,d1
   beq pplab_28
   bset.l #28,d2
pplab_28:
   btst.l #10,d1
   beq pplab_29
   bset.l #29,d2
pplab_29:
   btst.l #3,d1
   beq pplab_30
   bset.l #30,d2
pplab_30:
   btst.l #24,d1
   beq pplab_31
   bset.l #31,d2
pplab_31:

*
* All of this has been done on the right hand part (RHP) of the block
* (the upper long word). We now exclusive-or the result with the LHP;
* the original RHP becomes the LHP while the result becomes the new
* RHP
*

   eor.l d5,d2
   move.l d6,d5
   move.l d2,d6   ; note that the new RHP is in both d2 and d6.
                  ; This is assumed at the top of this loop

*
* This is the end of the main iteration loop.
*
   dbra d7,main_iter

*
* Now exchange RHP and LHP before performing the final iteration
*

   move.l d5,RHP
   move.l d6,LHP

* do final perm

   movea.l #LHP,a0         ; pointer to  data
   movea.l #ip_tab,a1      ; initial perm tab (used in the 'active' mode)
   clr.l d0                ; index into ip_tab
   moveq.l #1,d1           ; counter for loop over input data words
   clr.l d5                ; (temp buffer for low order bits)
   clr.l d6                ; (temp buffer for hi order bits)

fp_lw_loop:

   move.l (a0)+,d2         ; set up input data word
   moveq.l #3,d3           ; set up counter for loop over data bytes
                           ; (we do each byte in two loops of 4 bits)

fp_byte_loop:

   moveq.l #3,d7

fp_unib_loop:

   asr.l #1,d2
   bcc fp_no_bit_u
   move.l (a1),d4
   or.l d4,d6

fp_no_bit_u:

   addq.l #4,a1
   dbra d7,fp_unib_loop

   moveq.l #3,d7

fp_lnib_loop:

   asr.l #1,d2
   bcc fp_no_bit_l
   move.l (a1),d4
   or.l d4,d5

fp_no_bit_l:

   addq.l #4,a1
   dbra d7,fp_lnib_loop

   dbra d3,fp_byte_loop
   dbra d1,fp_lw_loop

   movea.l 8(a5),a2       ; buffer for permuted data
   move.l d5,(a2)+
   move.l d6,(a2)


   movem.l (a7)+,d2-d7/a2-a4/a6
   unlk a5
   rts

   END
