home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / SAFER / SAFER.ASM next >
Assembly Source File  |  1996-06-14  |  14KB  |  415 lines

  1.         INCLUDE MISC.INC
  2.         MODULE SAFER
  3.  
  4.         .386
  5.  
  6.         PUBLIC    _saferEncryptBlock, _saferDecryptBlock
  7.  
  8. ; Code to implement the improved SAFER-SK form of the SAFER cipher,
  9. ; originally published as "SAFER K-64: A Byte-Oriented Block-Ciphering
  10. ; Algorithm", James L. Massey, "Fast Software Encryption", Lecture Notes in
  11. ; Computer Science No. 809, Springer-Verlag 1994, p.1.  This code implements
  12. ; the 128-bit key extension designed by the Special Projects Team of the
  13. ; Ministry of Home Affairs, Singapore and published as "SAFER K-64: One Year
  14. ; Later", James L.Massey, presented at the K. U. Leuven Workshop on
  15. ; Algorithms, Leuven, Belgium, 14-16 December, 1994, to appear in "Fast
  16. ; Software Encryption II", Lecture Notes in Computer Science, Springer-Verlag
  17. ; 1995, along with Lars Knudsen's strengthened key schedule, presented in
  18. ; "A Key-Schedule Weakness in SAFER K-64," Lars Knudsen, presented at Crypto
  19. ; '95 in Santa Barbara, California.
  20. ;
  21. ; All parts of the SAFER-SK algorithm are non-proprietary and freely
  22. ; available for anyone to use as they see fit.
  23. ;
  24. ; Written 4 December 1995, Peter Gutmann <pgut01@cs.auckland.ac.nz>.
  25. ;
  26. ; This version is about 3 times as fast as the C implementation.
  27.  
  28. ; The two-point Pseudo-Hadamard Transform
  29. ;
  30. ;    b1 = 2a1 + a2
  31. ;    b2 =  a1 + a2
  32. ;
  33. ; and inverse two-point Pseudo-Hadamard Transform
  34. ;
  35. ;    a1 =  b1 -  b2
  36. ;    a2 = -b1 + 2b2
  37. ;
  38. ; which are used to create a three-dimensional PHT (ie independant two-point
  39. ; PHT's in each of three dimensions, which is why there are 2^3 = 8 bytes in
  40. ; the input and output of the PHT) through a decimation-by-two/fanning-out-
  41. ; by-two network.  The PHT provides guaranteed complete diffusion within one
  42. ; linear layer.
  43.  
  44. PHT1 MACRO x, y
  45.     add y, x
  46. ENDM
  47.  
  48. PHT2 MACRO x, y
  49.     add x, y
  50. ENDM
  51.  
  52. IPHT1 MACRO x, y
  53.     sub x, y
  54. ENDM
  55.  
  56. IPHT2 MACRO x, y
  57.     sub y, x
  58. ENDM
  59.  
  60. ; Since we have a great many independant operations we can interleave the two
  61. ; parts of the transform:
  62. ;
  63. ;    PHT(x,y) -> { y += x; x += y; }
  64. ;
  65. ; with the PHT's surrounding it to eliminate pipeline stalls, and the same
  66. ; for the IPHT.  Therefore we define the PHT in two parts PHT1 and PHT2 with
  67. ; a four-instruction interleave between the halves.
  68.  
  69. interleavePHT MACRO a, b, c, d, e, f, g, h
  70.     PHT1 a, b
  71.     PHT1 c, d
  72.     PHT1 e, f
  73.     PHT1 g, h
  74.     PHT2 a, b                        ; PHT( a, b );
  75.     PHT2 c, d                        ; PHT( c, d );
  76.     PHT2 e, f                        ; PHT( e, f );
  77.     PHT2 g, h                        ; PHT( g, h );
  78. ENDM
  79.  
  80. interleaveIPHT MACRO a, b, c, d, e, f, g, h
  81.     IPHT1 a, b
  82.     IPHT1 c, d
  83.     IPHT1 e, f
  84.     IPHT1 g, h
  85.     IPHT2 a, b                        ; PHT( a, b );
  86.     IPHT2 c, d                        ; PHT( c, d );
  87.     IPHT2 e, f                        ; PHT( e, f );
  88.     IPHT2 g, h                        ; PHT( g, h );
  89. ENDM
  90.  
  91. ; Load the word register corresponding to a byte half-register into an
  92. ; address-capable word register in preparation for using it to index memory.
  93.  
  94. loadWordReg MACRO wordReg, byteReg
  95.   IF byteReg EQ al OR byteReg EQ ah
  96.     mov wordReg, ax
  97.   ELSEIF byteReg EQ bl OR byteReg EQ bh
  98.     mov wordReg, bx
  99.   ELSEIF byteReg EQ cl OR byteReg EQ ch
  100.     mov wordReg, cx
  101.   ELSEIF byteReg EQ dl OR byteReg EQ dh
  102.     mov wordReg, dx
  103.   ELSE
  104.     ERROR Incorrect byte register passed to loadWordReg
  105.   ENDIF
  106. ENDM
  107.  
  108. ; Perform the mixed xor/byte addition of the round input with the subkey
  109. ; K2i-1, combined with the first level of the nonlinear layer, either
  110. ; 45^n mod 257 or log45n, and the mixed xor/byte addition with the subkey
  111. ; K2i.  We interleave two sets of operations to reduce pipeline stalls and
  112. ; make the maximum use of all available registers.
  113.  
  114. nonLinear MACRO reg1, op1, table1, reg2, op2, table2, keyOfs
  115.     op1 reg1, es:[di+keyOfs]
  116.     op2 reg2, es:[di+keyOfs+1]
  117.     loadWordReg si, reg1
  118.     loadWordReg bp, reg2
  119.     and si, 0FFh
  120.     shr bp, 8
  121.     mov reg1, es:[di+keyOfs+8]
  122.     mov reg2, es:[di+keyOfs+9]
  123.     op2 reg1, table1[si]
  124.     op1 reg2, table2[bp]
  125. ENDM
  126.  
  127. ; Perform the mixed xor/byte addition of the inverse PHT output with the
  128. ; subkey K2r+2-2i, combined with the second level of the nonlinear layer,
  129. ; either 45^n mod 257 or log45n, and finally the mixed xor/byte addition of
  130. ; the round output with K2r+1-2i.  We interleave two sets of operations to
  131. ; reduce pipeline stalls and make the maximum use of all available registers.
  132.  
  133. nonLinearInv MACRO reg1, op1, table1, reg2, op2, table2, keyOfs
  134.     op1 reg1, es:[di+keyOfs]
  135.     op2 reg2, es:[di+keyOfs-1]
  136.     loadWordReg si, reg1
  137.     loadWordReg bp, reg2
  138.     shr si, 8
  139.     and bp, 0FFh
  140.     mov reg1, table1[si]
  141.     mov reg2, table2[bp]
  142.     op2 reg1, es:[di+keyOfs-8]
  143.     op1 reg2, es:[di+keyOfs-9]
  144. ENDM
  145.  
  146. ; Rotate three bytes by one byte to the left.  This transforms a b c to
  147. ; b c a in two swaps.
  148.  
  149. swapData MACRO a, b, c
  150.     xchg a, c
  151.     xchg a, b
  152. ENDM
  153.  
  154. ; Symbolic defines for the byte values used in SAFER
  155.  
  156. A    EQU        al
  157. B    EQU        ah
  158. C    EQU        bl
  159. D    EQU        bh
  160. E    EQU        cl
  161. F    EQU        ch
  162. G    EQU        dl
  163. H    EQU        dh
  164.  
  165.         DATA
  166.  
  167. ; The lookup table for logs and exponents.  These contain the powers of the
  168. ; primitive element 45 of GF( 257 ) (ie values of 45^n mod 257) in "expTable"
  169. ; with the corresponding logs base 45 stored in "logTable".  They may be
  170. ; calculated as follows:
  171. ;
  172. ;    exponent = 1;
  173. ;    for( i = 0; i < 256; i++ )
  174. ;        {
  175. ;        int exp = exponent & 0xFF;
  176. ;
  177. ;        expTable[ i ] = exp;
  178. ;        logTable[ exp ] = i;
  179. ;        exponent = ( exponent * 45 ) % 257;
  180. ;        }
  181.  
  182. expTable    DB    001h, 02Dh, 0E2h, 093h, 0BEh, 045h, 015h, 0AEh
  183.             DB    078h, 003h, 087h, 0A4h, 0B8h, 038h, 0CFh, 03Fh
  184.             DB    008h, 067h, 009h, 094h, 0EBh, 026h, 0A8h, 06Bh
  185.             DB    0BDh, 018h, 034h, 01Bh, 0BBh, 0BFh, 072h, 0F7h
  186.             DB    040h, 035h, 048h, 09Ch, 051h, 02Fh, 03Bh, 055h
  187.             DB    0E3h, 0C0h, 09Fh, 0D8h, 0D3h, 0F3h, 08Dh, 0B1h
  188.             DB    0FFh, 0A7h, 03Eh, 0DCh, 086h, 077h, 0D7h, 0A6h
  189.             DB    011h, 0FBh, 0F4h, 0BAh, 092h, 091h, 064h, 083h
  190.             DB    0F1h, 033h, 0EFh, 0DAh, 02Ch, 0B5h, 0B2h, 02Bh
  191.             DB    088h, 0D1h, 099h, 0CBh, 08Ch, 084h, 01Dh, 014h
  192.             DB    081h, 097h, 071h, 0CAh, 05Fh, 0A3h, 08Bh, 057h
  193.             DB    03Ch, 082h, 0C4h, 052h, 05Ch, 01Ch, 0E8h, 0A0h
  194.             DB    004h, 0B4h, 085h, 04Ah, 0F6h, 013h, 054h, 0B6h
  195.             DB    0DFh, 00Ch, 01Ah, 08Eh, 0DEh, 0E0h, 039h, 0FCh
  196.             DB    020h, 09Bh, 024h, 04Eh, 0A9h, 098h, 09Eh, 0ABh
  197.             DB    0F2h, 060h, 0D0h, 06Ch, 0EAh, 0FAh, 0C7h, 0D9h
  198.             DB    000h, 0D4h, 01Fh, 06Eh, 043h, 0BCh, 0ECh, 053h
  199.             DB    089h, 0FEh, 07Ah, 05Dh, 049h, 0C9h, 032h, 0C2h
  200.             DB    0F9h, 09Ah, 0F8h, 06Dh, 016h, 0DBh, 059h, 096h
  201.             DB    044h, 0E9h, 0CDh, 0E6h, 046h, 042h, 08Fh, 00Ah
  202.             DB    0C1h, 0CCh, 0B9h, 065h, 0B0h, 0D2h, 0C6h, 0ACh
  203.             DB    01Eh, 041h, 062h, 029h, 02Eh, 00Eh, 074h, 050h
  204.             DB    002h, 05Ah, 0C3h, 025h, 07Bh, 08Ah, 02Ah, 05Bh
  205.             DB    0F0h, 006h, 00Dh, 047h, 06Fh, 070h, 09Dh, 07Eh
  206.             DB    010h, 0CEh, 012h, 027h, 0D5h, 04Ch, 04Fh, 0D6h
  207.             DB    079h, 030h, 068h, 036h, 075h, 07Dh, 0E4h, 0EDh
  208.             DB    080h, 06Ah, 090h, 037h, 0A2h, 05Eh, 076h, 0AAh
  209.             DB    0C5h, 07Fh, 03Dh, 0AFh, 0A5h, 0E5h, 019h, 061h
  210.             DB    0FDh, 04Dh, 07Ch, 0B7h, 00Bh, 0EEh, 0ADh, 04Bh
  211.             DB    022h, 0F5h, 0E7h, 073h, 023h, 021h, 0C8h, 005h
  212.             DB    0E1h, 066h, 0DDh, 0B3h, 058h, 069h, 063h, 056h
  213.             DB    00Fh, 0A1h, 031h, 095h, 017h, 007h, 03Ah, 028h
  214.  
  215. logTable    DB    080h, 000h, 0B0h, 009h, 060h, 0EFh, 0B9h, 0FDh
  216.             DB    010h, 012h, 09Fh, 0E4h, 069h, 0BAh, 0ADh, 0F8h
  217.             DB    0C0h, 038h, 0C2h, 065h, 04Fh, 006h, 094h, 0FCh
  218.             DB    019h, 0DEh, 06Ah, 01Bh, 05Dh, 04Eh, 0A8h, 082h
  219.             DB    070h, 0EDh, 0E8h, 0ECh, 072h, 0B3h, 015h, 0C3h
  220.             DB    0FFh, 0ABh, 0B6h, 047h, 044h, 001h, 0ACh, 025h
  221.             DB    0C9h, 0FAh, 08Eh, 041h, 01Ah, 021h, 0CBh, 0D3h
  222.             DB    00Dh, 06Eh, 0FEh, 026h, 058h, 0DAh, 032h, 00Fh
  223.             DB    020h, 0A9h, 09Dh, 084h, 098h, 005h, 09Ch, 0BBh
  224.             DB    022h, 08Ch, 063h, 0E7h, 0C5h, 0E1h, 073h, 0C6h
  225.             DB    0AFh, 024h, 05Bh, 087h, 066h, 027h, 0F7h, 057h
  226.             DB    0F4h, 096h, 0B1h, 0B7h, 05Ch, 08Bh, 0D5h, 054h
  227.             DB    079h, 0DFh, 0AAh, 0F6h, 03Eh, 0A3h, 0F1h, 011h
  228.             DB    0CAh, 0F5h, 0D1h, 017h, 07Bh, 093h, 083h, 0BCh
  229.             DB    0BDh, 052h, 01Eh, 0EBh, 0AEh, 0CCh, 0D6h, 035h
  230.             DB    008h, 0C8h, 08Ah, 0B4h, 0E2h, 0CDh, 0BFh, 0D9h
  231.             DB    0D0h, 050h, 059h, 03Fh, 04Dh, 062h, 034h, 00Ah
  232.             DB    048h, 088h, 0B5h, 056h, 04Ch, 02Eh, 06Bh, 09Eh
  233.             DB    0D2h, 03Dh, 03Ch, 003h, 013h, 0FBh, 097h, 051h
  234.             DB    075h, 04Ah, 091h, 071h, 023h, 0BEh, 076h, 02Ah
  235.             DB    05Fh, 0F9h, 0D4h, 055h, 00Bh, 0DCh, 037h, 031h
  236.             DB    016h, 074h, 0D7h, 077h, 0A7h, 0E6h, 007h, 0DBh
  237.             DB    0A4h, 02Fh, 046h, 0F3h, 061h, 045h, 067h, 0E3h
  238.             DB    00Ch, 0A2h, 03Bh, 01Ch, 085h, 018h, 004h, 01Dh
  239.             DB    029h, 0A0h, 08Fh, 0B2h, 05Ah, 0D8h, 0A6h, 07Eh
  240.             DB    0EEh, 08Dh, 053h, 04Bh, 0A1h, 09Ah, 0C1h, 00Eh
  241.             DB    07Ah, 049h, 0A5h, 02Ch, 081h, 0C4h, 0C7h, 036h
  242.             DB    02Bh, 07Fh, 043h, 095h, 033h, 0F2h, 06Ch, 068h
  243.             DB    06Dh, 0F0h, 002h, 028h, 0CEh, 0DDh, 09Bh, 0EAh
  244.             DB    05Eh, 099h, 07Ch, 014h, 086h, 0CFh, 0E5h, 042h
  245.             DB    0B8h, 040h, 078h, 02Dh, 03Ah, 0E9h, 064h, 01Fh
  246.             DB    092h, 090h, 07Dh, 039h, 06Fh, 0E0h, 089h, 030h
  247.  
  248. ; Temporary variables
  249.  
  250. rounds        DW    0
  251.  
  252.         CODE
  253.  
  254. ; Encrypt a block of data with SAFER.
  255.  
  256. _saferEncryptBlock PROC NEAR
  257.     push bp
  258.     mov bp, sp
  259.     push si
  260.     push di                            ; Save register vars
  261.  
  262.     ; Copy the input block to machine registers
  263.     les di, [bp+6]                    ; ES:DI = data
  264.     mov ax, es:[di]                    ; a = data[ 0 ]; b = data[ 1 ];
  265.     mov bx, es:[di+2]                ; c = data[ 2 ]; d = data[ 3 ];
  266.     mov cx, es:[di+4]                ; e = data[ 4 ]; f = data[ 5 ];
  267.     mov dx, es:[di+6]                ; g = data[ 6 ]; h = data[ 7 ];
  268.  
  269.     ; Remember the number of rounds
  270.     push bp                            ; Save temporary register
  271.     les di, [bp+10]                    ; ES:DI = key
  272.     mov bp, es:[di]
  273.     and bp, 0FFh                    ; BP = rounds
  274.     mov rounds, bp
  275.     inc di
  276.  
  277. @@encryptLoop:
  278.     ; Perform the mixed xor/byte addition of the round input with the subkey
  279.     ; K2i-1, combined with the first level of the nonlinear layer, either
  280.     ; 45^n mod 257 or log45n, and the mixed xor/byte addition with the subkey
  281.     ; K2i.
  282.     nonLinear A, xor, expTable, B, add, logTable, 0
  283.     nonLinear C, add, logTable, D, xor, expTable, 2
  284.     nonLinear E, xor, expTable, F, add, logTable, 4
  285.     nonLinear G, add, logTable, H, xor, expTable, 6
  286.  
  287.     ; Perform the Pseudo-Hadamard Trasform of the round output.
  288.     interleavePHT A, B, C, D, E, F, G, H
  289.     interleavePHT A, C, E, G, B, D, F, H
  290.     interleavePHT A, E, B, F, C, G, D, H
  291.  
  292.     ; Swap the data octets around.  If we unrol the loop we can eliminate
  293.     ; this step through register renaming, although at four instructions
  294.     ; total it's not a major performance hit.
  295.     swapData B, E, C
  296.     swapData D, F, G
  297.  
  298.     ; Prepare for the next round
  299.     add di, 16                        ; key += 16;
  300.     dec rounds
  301.     jnz @@encryptLoop
  302.     pop bp                            ; Restore temporary register
  303.  
  304.     ; Perform the final mixed xor/byte addition output transformation using
  305.     ; K2r + 1
  306.     xor A, es:[di+0]                ; data[ 0 ] = a ^ key[ 0 ];
  307.     add B, es:[di+1]                ; data[ 1 ] = b + key[ 1 ];
  308.     add C, es:[di+2]                ; data[ 2 ] = c + key[ 2 ];
  309.     xor D, es:[di+3]                ; data[ 3 ] = d ^ key[ 3 ];
  310.     xor E, es:[di+4]                ; data[ 4 ] = e ^ key[ 4 ];
  311.     add F, es:[di+5]                ; data[ 5 ] = f + key[ 5 ];
  312.     add G, es:[di+6]                ; data[ 6 ] = g + key[ 6 ];
  313.     xor H, es:[di+7]                ; data[ 7 ] = h ^ key[ 7 ];
  314.     les di, [bp+6]                    ; ES:DI = data
  315.     mov es:[di+0], A
  316.     mov es:[di+1], B
  317.     mov es:[di+2], C
  318.     mov es:[di+3], D
  319.     mov es:[di+4], E
  320.     mov es:[di+5], F
  321.     mov es:[di+6], G
  322.     mov es:[di+7], H
  323.  
  324.     pop di
  325.     pop si                            ; Restore register vars
  326.     pop bp
  327.     ret
  328. _saferEncryptBlock ENDP
  329.  
  330. ; Decrypt a block of data with SAFER.
  331.  
  332. _saferDecryptBlock PROC NEAR
  333.     push bp
  334.     mov bp, sp
  335.     push si
  336.     push di                            ; Save register vars
  337.  
  338.     ; Copy the input block to machine registers
  339.     les di, [bp+6]                    ; ES:DI = data
  340.     mov ax, es:[di]                    ; a = data[ 0 ]; b = data[ 1 ];
  341.     mov bx, es:[di+2]                ; c = data[ 2 ]; d = data[ 3 ];
  342.     mov cx, es:[di+4]                ; e = data[ 4 ]; f = data[ 5 ];
  343.     mov dx, es:[di+6]                ; g = data[ 6 ]; h = data[ 7 ];
  344.  
  345.     ; Remember the number of rounds
  346.     push bp                            ; Save temporary register
  347.     les di, [bp+10]                    ; ES:DI = key
  348.     mov bp, es:[di]
  349.     and bp, 0FFh                    ; BP = rounds
  350.     mov rounds, bp
  351.  
  352.     ; Since we're now running throught the algorithm backwards, we move to
  353.     ; the end of the key and start from there.
  354.     add bp, bp
  355.     inc bp
  356.     shl bp, 3
  357.     add di, bp                        ; key += SAFER_BLOCKSIZE * ( 1 + 2 * rounds );
  358.  
  359.     ; Perform the initial mixed xor/byte addition input transformation
  360.     ; using K2r+1.
  361.     xor A, es:[di-7]                ; data[ 0 ] = a ^ key[ -7 ];
  362.     sub B, es:[di-6]                ; data[ 1 ] = b - key[ -6 ];
  363.     sub C, es:[di-5]                ; data[ 2 ] = c - key[ -5 ];
  364.     xor D, es:[di-4]                ; data[ 3 ] = d ^ key[ -4 ];
  365.     xor E, es:[di-3]                ; data[ 4 ] = e ^ key[ -3 ];
  366.     sub F, es:[di-2]                ; data[ 5 ] = f - key[ -2 ];
  367.     sub G, es:[di-1]                ; data[ 6 ] = g - key[ -1 ];
  368.     xor H, es:[di-0]                ; data[ 7 ] = h ^ key[ 0 ];
  369.     sub di, 8                        ; key -= 8;
  370.  
  371. @@decryptLoop:
  372.     ; Swap the data octets around.  If we unrol the loop we can eliminate
  373.     ; this step through register renaming, although at four instructions
  374.     ; total it's not a major performance hit.
  375.     swapData E, B, C
  376.     swapData F, D, G
  377.  
  378.     ; Perform the inverse Pseudo-Hadamard Trasform of the round input.
  379.     interleaveIPHT A, E, B, F, C, G, D, H
  380.     interleaveIPHT A, C, E, G, B, D, F, H
  381.     interleaveIPHT A, B, C, D, E, F, G, H
  382.  
  383.     ; Perform the mixed xor/byte addition of the inverse PHT output with
  384.     ; the subkey K2r+2-2i, combined with the second level of the nonlinear
  385.     ; layer, either 45^n mod 257 or log45n, and finally the mixed xor/byte
  386.     ; addition of the round output with K2r+1-2i.
  387.     nonLinearInv H, sub, logTable, G, xor, expTable, 0
  388.     nonLinearInv F, xor, expTable, E, sub, logTable, -2
  389.     nonLinearInv D, sub, logTable, C, xor, expTable, -4
  390.     nonLinearInv B, xor, expTable, A, sub, logTable, -6
  391.  
  392.     ; Prepare for the next round
  393.     sub di, 16                        ; key -= 16;
  394.     dec rounds
  395.     jnz @@decryptLoop
  396.     pop bp                            ; Restore temporary register
  397.  
  398.     ; Copy the result back to the data buffer
  399.     les di, [bp+6]                    ; ES:DI = data
  400.     mov es:[di+0], A
  401.     mov es:[di+1], B
  402.     mov es:[di+2], C
  403.     mov es:[di+3], D
  404.     mov es:[di+4], E
  405.     mov es:[di+5], F
  406.     mov es:[di+6], G
  407.     mov es:[di+7], H
  408.  
  409.     pop di
  410.     pop si                            ; Restore register vars
  411.     pop bp
  412.     ret
  413. _saferDecryptBlock ENDP
  414.     ENDMODULE
  415.