Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Twofish encryption for 3.0+ and 7.0+

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Twofish encryption for 3.0+ and 7.0+

    Code:
    #IF 0
    =====================================================================
                             Twofish Encryption
    =====================================================================
       
    The block cipher Twofish was created by Bruce Schneier, John 
    Kelsey, Doug Whiting, David Wagner, Chris Hall, and Niels 
    Ferguson.  The algorithm was one of five finalists in the 
    international Advanced Encryption Standard competition to select 
    a replacement for DES.  Information about Twofish can be obtained 
    from Counterpane Labs at: 
     http://www.counterpane.com/twofish.html  
       
    The implementation presented here is based on code in C++ and Java 
    from a variety of public domain sources.  Some aspects of the PB code 
    are based on an implementation by Brian Gladman, in which the 
    following note appears: 
    --------------------------------------------------------------------
    Copyright in this implementation is held by Dr B R Gladman but I 
    hereby give permission for its free direct or derivative use subject 
    to acknowledgment of its origin and compliance with any conditions 
    that the originators of the algorithm place on its exploitation. 
                                  [...]
    Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999
    --------------------------------------------------------------------
       
    The Twofish algorithm is unpatented, uncopyrighted, and free for any 
    use public or private, commercial or non-commercial.  
       
    This PB implementation is hereby placed in the public domain.  Use it 
    as you wish.  My hope is discourage reliance on home-grown encryption 
    schemes in favor of well-examined, strong, freely available 
    algorithms. 
       
    In this posting, test-bed code appears below the TWOFISH.BAS file 
    contents.  All code compiles with (and requires) either PBCC 3.0+ or 
    PBWIN 7.0+. 
       
    <U>Implementation Notes</U>
    -- Twofish requires a large set of constant values.  These values 
    can be hard-coded or generated at run-time depending on the 
    existence of the %MAKE_TABLES equate.  If the tables are 
    generated at run-time, the process occurs once only--during the 
    first call to Twofish_Init&(). 
       
    -- The algorithm operates on plaintext blocks of 16 bytes.  Encryption 
    of shorter blocks is possible only by padding the plaintext (often  
    with zero bytes), which can be accomplished through several methods.  
    The simplest of them assumes that the final byte of plaintext always 
    identifies the number of bytes of padding added, including the final 
    byte itself. 
       
    Examples: 
       
       total plaintext bytes         = 30
       plaintext blocks encrypted:   = 2
       final block                   = chr$(x1 to x14) + chr$(0,2)
       
       total plaintext bytes         = 40
       plaintext blocks encrypted:   = 3
       final block                   = chr$(x1 to x8) + chr$(0,0,0,0,0,0,0,8)
       
    -- Encryption key lengths can range from 1 to 32 bytes (8 to 256 
    bits). 
       
    -- Implementation here is handled through an #INCLUDE file.  No global 
    data is employed.  
       
    -- As presented, the code does not supply a ready-to-use encryption 
    application.  It offers necessary pieces only, as well as an 
    illustration of their use.  Always keep in mind that most encryption 
    is broken because of implementation flaws and weaknesses. 
       
    -- Because of the methods of data handling required for most 
    encryption and hashing, PowerBASIC's LONGs should be used to assure  
    correct bit-level results (as well as additional speed). 
       
    Thanks go to Ken Meyers for testing this version before I posted it on 
    the PB web site. 
       
    Greg Turgeon 07/2003
    #ENDIF
       
    DEFLNG A-Z
    '-- Rem out the following equate to hard-code the required constant values
    '%MAKE_TABLES   = -1
       
    %BLOCKSIZE     = 16
    %ENCRYPT       = 1
    %DECRYPT       = 2
       
    TYPE TWOFISH_CONTEXT
       Action         AS LONG
       UserKeyLength  AS LONG
       UserKey        AS LONG PTR
       InBlock        AS LONG PTR
       OutBlock       AS LONG PTR
       
       KLength        AS LONG
       Q_0            AS BYTE PTR
       Q_1            AS BYTE PTR
       MDS_Table      AS LONG PTR
       XKey           AS LONG PTR       'expanded key
       XKey_Buffer    AS STRING * (40*4)
       S_Box          AS LONG PTR
       S_Box_Buffer   AS STRING * (4*256*4)
    END TYPE
       
       
    '--------------------
    'Utility macros
       
    '--------------------
    MACRO Exit0 =function = 0 : exit function
       
    '--------------------
    MACRO zbs(x) =string$(x,0)
       
    '--------------------
    MACRO FUNCTION makebuffer(x)
    MACROTEMP s
    LOCAL s$
    s = zbs(x)
    END MACRO = strptr(s)
       
    '--------------------
    MACRO RepByte(x)
    ' x = x | (x<<8) | (x<<16) | (x<<24);
    !mov  eax, x
    !and  eax, &hff
    !mov  edx, eax
    !mov  ah, al
    !mov  dh, dl
    !shl  eax, 16
    !or   eax, edx
    !mov  x,   eax
    END MACRO
       
    '--------------------
    MACRO FUNCTION shiftlc(x,constant_shiftval)
    shl_ret = (x)
    !shl shl_ret, constant_shiftval
    END MACRO = shl_ret
    '--------------------
    MACRO FUNCTION shiftrc(x,constant_shiftval)
    shr_ret = (x)
    !shr shr_ret, constant_shiftval
    END MACRO = shr_ret
    '--------------------
    MACRO FUNCTION rotlc(x,constant_rotate_val)
    retval = (x)
    !rol retval, constant_rotate_val
    END MACRO = retval
    '--------------------
    MACRO FUNCTION rotrc(x,constant_rotate_val)
    retval = (x)
    !ror retval, constant_rotate_val
    END MACRO = retval
       
    '--------------------
    MACRO idx0 =0 of 3
    MACRO idx1 =1 of 3
    MACRO idx2 =2 of 3
    MACRO idx3 =3 of 3
       
    '--------------------
    MACRO FUNCTION byte3(x)
    byte_ret = (x)
    !mov   eax, byte_ret
    !shr   eax, 24
    !mov   byte_ret, eax
    END MACRO = byte_ret
       
    '--------------------
    MACRO FUNCTION byte2(x)
    byte_ret = (x)
    !mov   eax, byte_ret
    !shr   eax, 16
    !and   eax, &hff
    !mov   byte_ret, eax
    END MACRO = byte_ret
       
    '--------------------
    MACRO FUNCTION byte1(x)
    byte_ret = (x)
    !mov   eax, byte_ret
    !shr   eax, 8
    !and   eax, &hff
    !mov   byte_ret, eax
    END MACRO = byte_ret
       
    '--------------------
    MACRO FUNCTION byte0(x)
    byte_ret = (x)
    !mov   eax, byte_ret
    !and   eax, &hff
    !mov   byte_ret, eax
    END MACRO = byte_ret
       
    '--------------------
    ' context shorthand macros
    '--------------------
    MACRO q0(n)       =Ctx.@Q_0[n]
    MACRO q1(n)       =Ctx.@Q_1[n]
    MACRO mds(n1,n2)  =Ctx.@MDS_Table[n1,n2]
    MACRO sbox(n1,n2) =Ctx.@S_Box[n1,n2]
       
       
    DECLARE FUNCTION Twofish_Init&(Ctx AS TWOFISH_CONTEXT)
    DECLARE FUNCTION Set_Key&(Ctx AS TWOFISH_CONTEXT)
    DECLARE FUNCTION EncryptBlock&(Ctx AS TWOFISH_CONTEXT)
    DECLARE FUNCTION DecryptBlock&(Ctx AS TWOFISH_CONTEXT)
       
    DECLARE FUNCTION hFunction&(Ctx AS TWOFISH_CONTEXT, BYVAL XX&, BYVAL Key AS LONG PTR)
    DECLARE FUNCTION MDS_REM&(BYVAL p0&, BYVAL p1&)
    DECLARE FUNCTION MakeSBoxes&(Ctx AS TWOFISH_CONTEXT, BYVAL Key AS LONG PTR)
       
    #IF %def(%MAKE_TABLES)
    DECLARE FUNCTION QP(BYVAL N&, BYVAL X?)
    DECLARE FUNCTION Make_QTables&()
    DECLARE FUNCTION Make_MDSTables&()
    #ENDIF
       
       
    '====================
    FUNCTION Set_Key&(Ctx AS TWOFISH_CONTEXT)
    LOCAL i&, j&, a&, b&, retval&, sboxkey AS LONG PTR
       
    Twofish_Init Ctx
       
    select case as long Ctx.UserKeyLength
       case <= 16
          Ctx.KLength = 2
       case <= 24
          Ctx.KLength = 3
       case <= 32
          Ctx.KLength = 4
       case else
          Exit0
    end select
       
    i = 0
    do while i < 40
       a = hFunction&(Ctx,i,Ctx.UserKey)
       b = rotlc(hFunction&(Ctx,i+1,Ctx.UserKey+4),8)
       Ctx.@XKey[i]   = a + b
       Ctx.@XKey[i+1] = rotlc(a+2*b,9)
       incr i : incr i
    loop
       
    sboxkey = makebuffer(4*4)
    j = Ctx.KLength-1
    for i = 0 to Ctx.KLength-1
       a = Ctx.@UserKey[2*i]
       b = Ctx.@UserKey[2*i+1]
       @sboxkey[j] = MDS_REM&(a,b)
       decr j
    next i
       
    MakeSBoxes Ctx, sboxkey
    function = -1
    END FUNCTION
       
       
    '====================
    FUNCTION hFunction&(Ctx AS TWOFISH_CONTEXT, BYVAL XX&, BYVAL Key AS LONG PTR)
    LOCAL x&, t0&, t1&, t2&, t3&, retval&, byte_ret&, shl_ret&
    x = XX&
    RepByte(x)
    if Ctx.KLength = 4 then goto Length4
    if Ctx.KLength = 3 then goto Length3
    if Ctx.KLength = 2 then goto Length2
    Exit0
       
    Length4:
       t0 =         q1(byte0(x))
       t1 = shiftlc(q0(byte1(x)),8)
       t2 = shiftlc(q0(byte2(x)),16) 
       t3 = shiftlc(q1(byte3(x)),24)
       x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[6]
    Length3:
       t0 =         q1(byte0(x))
       t1 = shiftlc(q1(byte1(x)),8)
       t2 = shiftlc(q0(byte2(x)),16) 
       t3 = shiftlc(q0(byte3(x)),24)
       x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[4]
    Length2:
       t0 =         q0(byte0(x)) 
       t1 = shiftlc(q1(byte1(x)),8)
       t2 = shiftlc(q0(byte2(x)),16) 
       t3 = shiftlc(q1(byte3(x)),24)
       x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[2]
       
       t0 =         q0(byte0(x))
       t1 = shiftlc(q0(byte1(x)),8)
       t2 = shiftlc(q1(byte2(x)),16) 
       t3 = shiftlc(q1(byte3(x)),24)
       x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[0]
       
    t0 = byte0(x) : t1 = byte1(x) : t2 = byte2(x) : t3 = byte3(x)
    function = mds(t0 of 255,idx0) XOR _
               mds(t1 of 255,idx1) XOR _
               mds(t2 of 255,idx2) XOR _
               mds(t3 of 255,idx3)
    END FUNCTION
       
       
    %G_MOD         = &h0000014D???
    %SHR1MODULUS   = &h000000A6???   'shr %G_MOD, 1
    '====================
    FUNCTION MDS_REM&(BYVAL p0&, BYVAL p1&)
    LOCAL i&, t1&, t2&, t3&, tmp&, u&, retval&, shl_ret&, shr_ret&
    for i = 0 to 7
       t1 = p1&
       !shr t1, 24
       tmp = p1&
       !shl tmp, 8
       t2 = p0&
       !shr t2, 24
       p1& = tmp OR t2
       !shl p0&, 8
                
       u = t1
       !shl u, 1
       if(t1 AND &h80) then u = u XOR %G_MOD
       tmp = u
       !shl tmp, 16
       p1& = p1& XOR t1 XOR tmp
       tmp = t1
       !shr tmp, 1
       u = u XOR tmp
       if (t1 AND &h01) then u = u XOR %SHR1MODULUS
       t2 = u
       !shl t2, 24
       t3 = u
       !shl t3, 8
       p1& = p1& XOR t2 OR t3
    next i
    function = p1&
    END FUNCTION
       
    '-- Compiler limitation on nesting of macros requires the following forms:
    MACRO q20(n) =(Ctx.@Q_0[Ctx.@Q_0[n] XOR byte0(@key[1])] XOR byte0(@key[0]))
    MACRO q21(n) =(Ctx.@Q_0[Ctx.@Q_1[n] XOR byte1(@key[1])] XOR byte1(@key[0]))
    MACRO q22(n) =(Ctx.@Q_1[Ctx.@Q_0[n] XOR byte2(@key[1])] XOR byte2(@key[0]))
    MACRO q23(n) =(Ctx.@Q_1[Ctx.@Q_1[n] XOR byte3(@key[1])] XOR byte3(@key[0]))
       
    MACRO q30(n) =(Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_1[n] XOR byte0(@key2)] XOR byte0(@key1)] XOR byte0(@key0))
    MACRO q31(n) =(Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[n] XOR byte1(@key2)] XOR byte1(@key1)] XOR byte1(@key0))
    MACRO q32(n) =(Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_0[n] XOR byte2(@key2)] XOR byte2(@key1)] XOR byte2(@key0))
    MACRO q33(n) =(Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[n] XOR byte3(@key2)] XOR byte3(@key1)] XOR byte3(@key0))
       
    '-- NOTE: If cutting & pasting, line lengths of next four lines = 125 chars each
    MACRO q40(n) =(Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[n] XOR byte0(@key3)] XOR byte0(@key2)] XOR byte0(@key1)] XOR byte0(@key0))
    MACRO q41(n) =(Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[n] XOR byte1(@key3)] XOR byte1(@key2)] XOR byte1(@key1)] XOR byte1(@key0))
    MACRO q42(n) =(Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_0[n] XOR byte2(@key3)] XOR byte2(@key2)] XOR byte2(@key1)] XOR byte2(@key0))
    MACRO q43(n) =(Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_1[n] XOR byte3(@key3)] XOR byte3(@key2)] XOR byte3(@key1)] XOR byte3(@key0))
       
    '====================
    FUNCTION MakeSBoxes&(Ctx AS TWOFISH_CONTEXT, BYVAL Key AS LONG PTR)
    LOCAL i&, byte_ret&
    LOCAL key0 AS LONG PTR, key1 AS LONG PTR, key2 AS LONG PTR, key3 AS LONG PTR
    key0 = Key : key1 = key0 + 4 : key2 = key0 + 8 : key3 = key0 + 12
    select case as long Ctx.KLength
       case 2
          for i = 0 to 255
             sbox(i of 255,idx0) = mds(q20(i) of 255,idx0)
             sbox(i of 255,idx1) = mds(q21(i) of 255,idx1)
             sbox(i of 255,idx2) = mds(q22(i) of 255,idx2) 
             sbox(i of 255,idx3) = mds(q23(i) of 255,idx3)
          next i
       case 3
          for i = 0 to 255
             sbox(i of 255,idx0) = mds(q30(i) of 255,idx0)
             sbox(i of 255,idx1) = mds(q31(i) of 255,idx1)
             sbox(i of 255,idx2) = mds(q32(i) of 255,idx2)
             sbox(i of 255,idx3) = mds(q33(i) of 255,idx3)
          next i
       case 4
          for i = 0 to 255
             sbox(i of 255,idx0) = mds(q40(i) of 255,idx0)
             sbox(i of 255,idx1) = mds(q41(i) of 255,idx1)
             sbox(i of 255,idx2) = mds(q42(i) of 255,idx2)
             sbox(i of 255,idx3) = mds(q43(i) of 255,idx3)
          next i
    end select
    END FUNCTION
       
       
    '--------------------
    MACRO FUNCTION g0_fun(n)
    tt0 = sbox(byte0(n) of 255,idx0)
    tt1 = sbox(byte1(n) of 255,idx1)
    tt2 = sbox(byte2(n) of 255,idx2)
    tt3 = sbox(byte3(n) of 255,idx3)
    END MACRO = (tt0 XOR tt1 XOR tt2 XOR tt3)
       
    '--------------------
    MACRO FUNCTION g1_fun(n)
    tt0 = sbox(byte3(n) of 255,idx0)
    tt1 = sbox(byte0(n) of 255,idx1)
    tt2 = sbox(byte1(n) of 255,idx2)
    tt3 = sbox(byte2(n) of 255,idx3)
    END MACRO = (tt0 XOR tt1 XOR tt2 XOR tt3)
       
       
    '--------------------
    MACRO f_rnd(i)
    t1 = g1_fun(@blk[1]) : t0 = g0_fun(@blk[0])
    t  = @blk[2] XOR (t0 + t1 + Ctx.@XKey[4*i+8])
    !ror t, 1
    @blk[2] = t
    t  = @blk[3]
    !rol t, 1
    @blk[3] = t XOR (t0 + 2*t1 + Ctx.@XKey[4*i+9])
    t1 = g1_fun(@blk[3]) : t0 = g0_fun(@blk[2])
    t  = @blk[0] XOR (t0 + t1 + Ctx.@XKey[4*i+10])
    !ror t, 1
    @blk[0] = t
    t  = @blk[1]
    !rol t, 1
    @blk[1] = t XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+11])
    END MACRO
       
    '====================
    FUNCTION EncryptBlock&(Ctx AS TWOFISH_CONTEXT)
    LOCAL t&, t0&, t1&, tt0&, tt1&, tt2&, tt3&
    LOCAL byte_ret&, blk AS LONG PTR
       
    blk = makebuffer(%BLOCKSIZE)
    @blk[0] = Ctx.@InBlock[0] XOR Ctx.@XKey[0]
    @blk[1] = Ctx.@InBlock[1] XOR Ctx.@XKey[1]
    @blk[2] = Ctx.@InBlock[2] XOR Ctx.@XKey[2]
    @blk[3] = Ctx.@InBlock[3] XOR Ctx.@XKey[3]
       
    f_rnd(0) : f_rnd(1) : f_rnd(2) : f_rnd(3)
    f_rnd(4) : f_rnd(5) : f_rnd(6) : f_rnd(7)
       
    Ctx.@OutBlock[0] = @blk[2] XOR Ctx.@XKey[4]
    Ctx.@OutBlock[1] = @blk[3] XOR Ctx.@XKey[5]
    Ctx.@OutBlock[2] = @blk[0] XOR Ctx.@XKey[6]
    Ctx.@OutBlock[3] = @blk[1] XOR Ctx.@XKey[7] 
    END FUNCTION
       
       
    '--------------------
    MACRO i_rnd(i)
    t1 = g1_fun(@blk[1]) : t0 = g0_fun(@blk[0])
    t  = @blk[2]
    !rol t, 1
    @blk[2] = t XOR (t0 + t1 + Ctx.@XKey[4*i+10])
    t  = @blk[3] XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+11])
    !ror t, 1
    @blk[3] = t
    t1 = g1_fun(@blk[3]) : t0 = g0_fun(@blk[2])
    t  = @blk[0]
    !rol t, 1
    @blk[0] = t  XOR (t0 + t1 + Ctx.@XKey[4*i+8])
    t  = @blk[1] XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+9])
    !ror t, 1
    @blk[1] = t
    END MACRO
       
    '====================
    FUNCTION DecryptBlock&(Ctx AS TWOFISH_CONTEXT)
    LOCAL t&, t0&, t1&, tt0&, tt1&, tt2&, tt3&
    LOCAL byte_ret&, blk AS LONG PTR
       
    blk = makebuffer(%BLOCKSIZE)
    @blk[0] = Ctx.@InBlock[0] XOR Ctx.@XKey[4]
    @blk[1] = Ctx.@InBlock[1] XOR Ctx.@XKey[5]
    @blk[2] = Ctx.@InBlock[2] XOR Ctx.@XKey[6]
    @blk[3] = Ctx.@InBlock[3] XOR Ctx.@XKey[7]
       
    i_rnd(7) : i_rnd(6) : i_rnd(5) : i_rnd(4)
    i_rnd(3) : i_rnd(2) : i_rnd(1) : i_rnd(0)
       
    Ctx.@OutBlock[0] = @blk[2] XOR Ctx.@XKey[0]
    Ctx.@OutBlock[1] = @blk[3] XOR Ctx.@XKey[1]
    Ctx.@OutBlock[2] = @blk[0] XOR Ctx.@XKey[2]
    Ctx.@OutBlock[3] = @blk[1] XOR Ctx.@XKey[3] 
    END FUNCTION
       
       
    '====================
    FUNCTION Twofish_Init&(Ctx AS TWOFISH_CONTEXT)
    STATIC pQTable0&, pQTable1&, pMDSTables&
    Ctx.S_Box_Buffer  = zbs(sizeof(Ctx.S_Box_Buffer))
    Ctx.S_Box         = varptr(Ctx.S_Box_Buffer)
    Ctx.XKey_Buffer   = zbs(sizeof(Ctx.XKey_Buffer))
    Ctx.XKey          = varptr(Ctx.XKey_Buffer)
       
    if pQTable0 = 0 then
       #IF %def(%MAKE_TABLES)
       pQTable0       = Make_QTables&
       pQTable1       = pQTable0 + 256
       pMDSTables     = Make_MDSTables&
       #ELSE
       pQTable0       = codeptr(Q_0)
       pQTable1       = codeptr(Q_1)
       pMDSTables     = codeptr(M_D_S)
       #ENDIF
    end if
    Ctx.Q_0           = pQTable0
    Ctx.Q_1           = pQTable1
    Ctx.MDS_Table     = pMDSTables
       
    #IF NOT %def(%MAKE_TABLES)
    exit function
    Q_0:
    !DB   &hA9, &h67, &hB3, &hE8, &h04, &hFD, &hA3, &h76, &h9A, &h92, &h80, &h78
    !DB   &hE4, &hDD, &hD1, &h38, &h0D, &hC6, &h35, &h98, &h18, &hF7, &hEC, &h6C
    !DB   &h43, &h75, &h37, &h26, &hFA, &h13, &h94, &h48, &hF2, &hD0, &h8B, &h30
    !DB   &h84, &h54, &hDF, &h23, &h19, &h5B, &h3D, &h59, &hF3, &hAE, &hA2, &h82
    !DB   &h63, &h01, &h83, &h2E, &hD9, &h51, &h9B, &h7C, &hA6, &hEB, &hA5, &hBE
    !DB   &h16, &h0C, &hE3, &h61, &hC0, &h8C, &h3A, &hF5, &h73, &h2C, &h25, &h0B
    !DB   &hBB, &h4E, &h89, &h6B, &h53, &h6A, &hB4, &hF1, &hE1, &hE6, &hBD, &h45
    !DB   &hE2, &hF4, &hB6, &h66, &hCC, &h95, &h03, &h56, &hD4, &h1C, &h1E, &hD7
    !DB   &hFB, &hC3, &h8E, &hB5, &hE9, &hCF, &hBF, &hBA, &hEA, &h77, &h39, &hAF
    !DB   &h33, &hC9, &h62, &h71, &h81, &h79, &h09, &hAD, &h24, &hCD, &hF9, &hD8
    !DB   &hE5, &hC5, &hB9, &h4D, &h44, &h08, &h86, &hE7, &hA1, &h1D, &hAA, &hED
    !DB   &h06, &h70, &hB2, &hD2, &h41, &h7B, &hA0, &h11, &h31, &hC2, &h27, &h90
    !DB   &h20, &hF6, &h60, &hFF, &h96, &h5C, &hB1, &hAB, &h9E, &h9C, &h52, &h1B
    !DB   &h5F, &h93, &h0A, &hEF, &h91, &h85, &h49, &hEE, &h2D, &h4F, &h8F, &h3B
    !DB   &h47, &h87, &h6D, &h46, &hD6, &h3E, &h69, &h64, &h2A, &hCE, &hCB, &h2F
    !DB   &hFC, &h97, &h05, &h7A, &hAC, &h7F, &hD5, &h1A, &h4B, &h0E, &hA7, &h5A
    !DB   &h28, &h14, &h3F, &h29, &h88, &h3C, &h4C, &h02, &hB8, &hDA, &hB0, &h17
    !DB   &h55, &h1F, &h8A, &h7D, &h57, &hC7, &h8D, &h74, &hB7, &hC4, &h9F, &h72
    !DB   &h7E, &h15, &h22, &h12, &h58, &h07, &h99, &h34, &h6E, &h50, &hDE, &h68
    !DB   &h65, &hBC, &hDB, &hF8, &hC8, &hA8, &h2B, &h40, &hDC, &hFE, &h32, &hA4
    !DB   &hCA, &h10, &h21, &hF0, &hD3, &h5D, &h0F, &h00, &h6F, &h9D, &h36, &h42
    !DB   &h4A, &h5E, &hC1, &hE0
    Q_1:
    !DB   &h75, &hF3, &hC6, &hF4, &hDB, &h7B, &hFB, &hC8, &h4A, &hD3, &hE6, &h6B
    !DB   &h45, &h7D, &hE8, &h4B, &hD6, &h32, &hD8, &hFD, &h37, &h71, &hF1, &hE1
    !DB   &h30, &h0F, &hF8, &h1B, &h87, &hFA, &h06, &h3F, &h5E, &hBA, &hAE, &h5B
    !DB   &h8A, &h00, &hBC, &h9D, &h6D, &hC1, &hB1, &h0E, &h80, &h5D, &hD2, &hD5
    !DB   &hA0, &h84, &h07, &h14, &hB5, &h90, &h2C, &hA3, &hB2, &h73, &h4C, &h54
    !DB   &h92, &h74, &h36, &h51, &h38, &hB0, &hBD, &h5A, &hFC, &h60, &h62, &h96
    !DB   &h6C, &h42, &hF7, &h10, &h7C, &h28, &h27, &h8C, &h13, &h95, &h9C, &hC7
    !DB   &h24, &h46, &h3B, &h70, &hCA, &hE3, &h85, &hCB, &h11, &hD0, &h93, &hB8
    !DB   &hA6, &h83, &h20, &hFF, &h9F, &h77, &hC3, &hCC, &h03, &h6F, &h08, &hBF
    !DB   &h40, &hE7, &h2B, &hE2, &h79, &h0C, &hAA, &h82, &h41, &h3A, &hEA, &hB9
    !DB   &hE4, &h9A, &hA4, &h97, &h7E, &hDA, &h7A, &h17, &h66, &h94, &hA1, &h1D
    !DB   &h3D, &hF0, &hDE, &hB3, &h0B, &h72, &hA7, &h1C, &hEF, &hD1, &h53, &h3E
    !DB   &h8F, &h33, &h26, &h5F, &hEC, &h76, &h2A, &h49, &h81, &h88, &hEE, &h21
    !DB   &hC4, &h1A, &hEB, &hD9, &hC5, &h39, &h99, &hCD, &hAD, &h31, &h8B, &h01
    !DB   &h18, &h23, &hDD, &h1F, &h4E, &h2D, &hF9, &h48, &h4F, &hF2, &h65, &h8E
    !DB   &h78, &h5C, &h58, &h19, &h8D, &hE5, &h98, &h57, &h67, &h7F, &h05, &h64
    !DB   &hAF, &h63, &hB6, &hFE, &hF5, &hB7, &h3C, &hA5, &hCE, &hE9, &h68, &h44
    !DB   &hE0, &h4D, &h43, &h69, &h29, &h2E, &hAC, &h15, &h59, &hA8, &h0A, &h9E
    !DB   &h6E, &h47, &hDF, &h34, &h35, &h6A, &hCF, &hDC, &h22, &hC9, &hC0, &h9B
    !DB   &h89, &hD4, &hED, &hAB, &h12, &hA2, &h0D, &h52, &hBB, &h02, &h2F, &hA9
    !DB   &hD7, &h61, &h1E, &hB4, &h50, &h04, &hF6, &hC2, &h16, &h25, &h86, &h56
    !DB   &h55, &h09, &hBE, &h91
       
    M_D_S:
    ' idx0:
    ! DD  &hbcbc3275, &hecec21f3, &h202043c6, &hb3b3c9f4, &hdada03db, &h02028b7b, &he2e22bfb, &h9e9efac8
    ! DD  &hc9c9ec4a, &hd4d409d3, &h18186be6, &h1e1e9f6b, &h98980e45, &hb2b2387d, &ha6a6d2e8, &h2626b74b
    ! DD  &h3c3c57d6, &h93938a32, &h8282eed8, &h525298fd, &h7b7bd437, &hbbbb3771, &h5b5b97f1, &h474783e1
    ! DD  &h24243c30, &h5151e20f, &hbabac6f8, &h4a4af31b, &hbfbf4887, &h0d0d70fa, &hb0b0b306, &h7575de3f
    ! DD  &hd2d2fd5e, &h7d7d20ba, &h666631ae, &h3a3aa35b, &h59591c8a, &h00000000, &hcdcd93bc, &h1a1ae09d
    ! DD  &haeae2c6d, &h7f7fabc1, &h2b2bc7b1, &hbebeb90e, &he0e0a080, &h8a8a105d, &h3b3b52d2, &h6464bad5
    ! DD  &hd8d888a0, &he7e7a584, &h5f5fe807, &h1b1b1114, &h2c2cc2b5, &hfcfcb490, &h3131272c, &h808065a3
    ! DD  &h73732ab2, &h0c0c8173, &h79795f4c, &h6b6b4154, &h4b4b0292, &h53536974, &h94948f36, &h83831f51
    ! DD  &h2a2a3638, &hc4c49cb0, &h2222c8bd, &hd5d5f85a, &hbdbdc3fc, &h48487860, &hffffce62, &h4c4c0796
    ! DD  &h4141776c, &hc7c7e642, &hebeb24f7, &h1c1c1410, &h5d5d637c, &h36362228, &h6767c027, &he9e9af8c
    ! DD  &h4444f913, &h1414ea95, &hf5f5bb9c, &hcfcf18c7, &h3f3f2d24, &hc0c0e346, &h7272db3b, &h54546c70
    ! DD  &h29294cca, &hf0f035e3, &h0808fe85, &hc6c617cb, &hf3f34f11, &h8c8ce4d0, &ha4a45993, &hcaca96b8
    ! DD  &h68683ba6, &hb8b84d83, &h38382820, &he5e52eff, &hadad569f, &h0b0b8477, &hc8c81dc3, &h9999ffcc
    ! DD  &h5858ed03, &h19199a6f, &h0e0e0a08, &h95957ebf, &h70705040, &hf7f730e7, &h6e6ecf2b, &h1f1f6ee2
    ! DD  &hb5b53d79, &h09090f0c, &h616134aa, &h57571682, &h9f9f0b41, &h9d9d803a, &h111164ea, &h2525cdb9
    ! DD  &hafafdde4, &h4545089a, &hdfdf8da4, &ha3a35c97, &heaead57e, &h353558da, &hededd07a, &h4343fc17
    ! DD  &hf8f8cb66, &hfbfbb194, &h3737d3a1, &hfafa401d, &hc2c2683d, &hb4b4ccf0, &h32325dde, &h9c9c71b3
    ! DD  &h5656e70b, &he3e3da72, &h878760a7, &h15151b1c, &hf9f93aef, &h6363bfd1, &h3434a953, &h9a9a853e
    ! DD  &hb1b1428f, &h7c7cd133, &h88889b26, &h3d3da65f, &ha1a1d7ec, &he4e4df76, &h8181942a, &h91910149
    ! DD  &h0f0ffb81, &heeeeaa88, &h161661ee, &hd7d77321, &h9797f5c4, &ha5a5a81a, &hfefe3feb, &h6d6db5d9
    ! DD  &h7878aec5, &hc5c56d39, &h1d1de599, &h7676a4cd, &h3e3edcad, &hcbcb6731, &hb6b6478b, &hefef5b01
    ! DD  &h12121e18, &h6060c523, &h6a6ab0dd, &h4d4df61f, &hcecee94e, &hdede7c2d, &h55559df9, &h7e7e5a48
    ! DD  &h2121b24f, &h03037af2, &ha0a02665, &h5e5e198e, &h5a5a6678, &h65654b5c, &h62624e58, &hfdfd4519
    ! DD  &h0606f48d, &h404086e5, &hf2f2be98, &h3333ac57, &h17179067, &h05058e7f, &he8e85e05, &h4f4f7d64
    ! DD  &h89896aaf, &h10109563, &h74742fb6, &h0a0a75fe, &h5c5c92f5, &h9b9b74b7, &h2d2d333c, &h3030d6a5
    ! DD  &h2e2e49ce, &h494989e9, &h46467268, &h77775544, &ha8a8d8e0, &h9696044d, &h2828bd43, &ha9a92969
    ! DD  &hd9d97929, &h8686912e, &hd1d187ac, &hf4f44a15, &h8d8d1559, &hd6d682a8, &hb9b9bc0a, &h42420d9e
    ! DD  &hf6f6c16e, &h2f2fb847, &hdddd06df, &h23233934, &hcccc6235, &hf1f1c46a, &hc1c112cf, &h8585ebdc
    ! DD  &h8f8f9e22, &h7171a1c9, &h9090f0c0, &haaaa539b, &h0101f189, &h8b8be1d4, &h4e4e8ced, &h8e8e6fab
    ! DD  &hababa212, &h6f6f3ea2, &he6e6540d, &hdbdbf252, &h92927bbb, &hb7b7b602, &h6969ca2f, &h3939d9a9
    ! DD  &hd3d30cd7, &ha7a72361, &ha2a2ad1e, &hc3c399b4, &h6c6c4450, &h07070504, &h04047ff6, &h272746c2
    ! DD  &hacaca716, &hd0d07625, &h50501386, &hdcdcf756, &h84841a55, &he1e15109, &h7a7a25be, &h1313ef91
    ' idx1:
    ! DD  &ha9d93939, &h67901717, &hb3719c9c, &he8d2a6a6, &h04050707, &hfd985252, &ha3658080, &h76dfe4e4
    ! DD  &h9a084545, &h92024b4b, &h80a0e0e0, &h78665a5a, &he4ddafaf, &hddb06a6a, &hd1bf6363, &h38362a2a
    ! DD  &h0d54e6e6, &hc6432020, &h3562cccc, &h98bef2f2, &h181e1212, &hf724ebeb, &hecd7a1a1, &h6c774141
    ! DD  &h43bd2828, &h7532bcbc, &h37d47b7b, &h269b8888, &hfa700d0d, &h13f94444, &h94b1fbfb, &h485a7e7e
    ! DD  &hf27a0303, &hd0e48c8c, &h8b47b6b6, &h303c2424, &h84a5e7e7, &h54416b6b, &hdf06dddd, &h23c56060
    ! DD  &h1945fdfd, &h5ba33a3a, &h3d68c2c2, &h59158d8d, &hf321ecec, &hae316666, &ha23e6f6f, &h82165757
    ! DD  &h63951010, &h015befef, &h834db8b8, &h2e918686, &hd9b56d6d, &h511f8383, &h9b53aaaa, &h7c635d5d
    ! DD  &ha63b6868, &heb3ffefe, &ha5d63030, &hbe257a7a, &h16a7acac, &h0c0f0909, &he335f0f0, &h6123a7a7
    ! DD  &hc0f09090, &h8cafe9e9, &h3a809d9d, &hf5925c5c, &h73810c0c, &h2c273131, &h2576d0d0, &h0be75656
    ! DD  &hbb7b9292, &h4ee9cece, &h89f10101, &h6b9f1e1e, &h53a93434, &h6ac4f1f1, &hb499c3c3, &hf1975b5b
    ! DD  &he1834747, &he66b1818, &hbdc82222, &h450e9898, &he26e1f1f, &hf4c9b3b3, &hb62f7474, &h66cbf8f8
    ! DD  &hccff9999, &h95ea1414, &h03ed5858, &h56f7dcdc, &hd4e18b8b, &h1c1b1515, &h1eada2a2, &hd70cd3d3
    ! DD  &hfb2be2e2, &hc31dc8c8, &h8e195e5e, &hb5c22c2c, &he9894949, &hcf12c1c1, &hbf7e9595, &hba207d7d
    ! DD  &hea641111, &h77840b0b, &h396dc5c5, &haf6a8989, &h33d17c7c, &hc9a17171, &h62ceffff, &h7137bbbb
    ! DD  &h81fb0f0f, &h793db5b5, &h0951e1e1, &haddc3e3e, &h242d3f3f, &hcda47676, &hf99d5555, &hd8ee8282
    ! DD  &he5864040, &hc5ae7878, &hb9cd2525, &h4d049696, &h44557777, &h080a0e0e, &h86135050, &he730f7f7
    ! DD  &ha1d33737, &h1d40fafa, &haa346161, &hed8c4e4e, &h06b3b0b0, &h706c5454, &hb22a7373, &hd2523b3b
    ! DD  &h410b9f9f, &h7b8b0202, &ha088d8d8, &h114ff3f3, &h3167cbcb, &hc2462727, &h27c06767, &h90b4fcfc
    ! DD  &h20283838, &hf67f0404, &h60784848, &hff2ee5e5, &h96074c4c, &h5c4b6565, &hb1c72b2b, &hab6f8e8e
    ! DD  &h9e0d4242, &h9cbbf5f5, &h52f2dbdb, &h1bf34a4a, &h5fa63d3d, &h9359a4a4, &h0abcb9b9, &hef3af9f9
    ! DD  &h91ef1313, &h85fe0808, &h49019191, &hee611616, &h2d7cdede, &h4fb22121, &h8f42b1b1, &h3bdb7272
    ! DD  &h47b82f2f, &h8748bfbf, &h6d2caeae, &h46e3c0c0, &hd6573c3c, &h3e859a9a, &h6929a9a9, &h647d4f4f
    ! DD  &h2a948181, &hce492e2e, &hcb17c6c6, &h2fca6969, &hfcc3bdbd, &h975ca3a3, &h055ee8e8, &h7ad0eded
    ! DD  &hac87d1d1, &h7f8e0505, &hd5ba6464, &h1aa8a5a5, &h4bb72626, &h0eb9bebe, &ha7608787, &h5af8d5d5
    ! DD  &h28223636, &h14111b1b, &h3fde7575, &h2979d9d9, &h88aaeeee, &h3c332d2d, &h4c5f7979, &h02b6b7b7
    ! DD  &hb896caca, &hda583535, &hb09cc4c4, &h17fc4343, &h551a8484, &h1ff64d4d, &h8a1c5959, &h7d38b2b2
    ! DD  &h57ac3333, &hc718cfcf, &h8df40606, &h74695353, &hb7749b9b, &hc4f59797, &h9f56adad, &h72dae3e3
    ! DD  &h7ed5eaea, &h154af4f4, &h229e8f8f, &h12a2abab, &h584e6262, &h07e85f5f, &h99e51d1d, &h34392323
    ! DD  &h6ec1f6f6, &h50446c6c, &hde5d3232, &h68724646, &h6526a0a0, &hbc93cdcd, &hdb03dada, &hf8c6baba
    ! DD  &hc8fa9e9e, &ha882d6d6, &h2bcf6e6e, &h40507070, &hdceb8585, &hfe750a0a, &h328a9393, &ha48ddfdf
    ! DD  &hca4c2929, &h10141c1c, &h2173d7d7, &hf0ccb4b4, &hd309d4d4, &h5d108a8a, &h0fe25151, &h00000000
    ! DD  &h6f9a1919, &h9de01a1a, &h368f9494, &h42e6c7c7, &h4aecc9c9, &h5efdd2d2, &hc1ab7f7f, &he0d8a8a8
    ' idx2:
    ! DD  &hbc75bc32, &hecf3ec21, &h20c62043, &hb3f4b3c9, &hdadbda03, &h027b028b, &he2fbe22b, &h9ec89efa
    ! DD  &hc94ac9ec, &hd4d3d409, &h18e6186b, &h1e6b1e9f, &h9845980e, &hb27db238, &ha6e8a6d2, &h264b26b7
    ! DD  &h3cd63c57, &h9332938a, &h82d882ee, &h52fd5298, &h7b377bd4, &hbb71bb37, &h5bf15b97, &h47e14783
    ! DD  &h2430243c, &h510f51e2, &hbaf8bac6, &h4a1b4af3, &hbf87bf48, &h0dfa0d70, &hb006b0b3, &h753f75de
    ! DD  &hd25ed2fd, &h7dba7d20, &h66ae6631, &h3a5b3aa3, &h598a591c, &h00000000, &hcdbccd93, &h1a9d1ae0
    ! DD  &hae6dae2c, &h7fc17fab, &h2bb12bc7, &hbe0ebeb9, &he080e0a0, &h8a5d8a10, &h3bd23b52, &h64d564ba
    ! DD  &hd8a0d888, &he784e7a5, &h5f075fe8, &h1b141b11, &h2cb52cc2, &hfc90fcb4, &h312c3127, &h80a38065
    ! DD  &h73b2732a, &h0c730c81, &h794c795f, &h6b546b41, &h4b924b02, &h53745369, &h9436948f, &h8351831f
    ! DD  &h2a382a36, &hc4b0c49c, &h22bd22c8, &hd55ad5f8, &hbdfcbdc3, &h48604878, &hff62ffce, &h4c964c07
    ! DD  &h416c4177, &hc742c7e6, &hebf7eb24, &h1c101c14, &h5d7c5d63, &h36283622, &h672767c0, &he98ce9af
    ! DD  &h441344f9, &h149514ea, &hf59cf5bb, &hcfc7cf18, &h3f243f2d, &hc046c0e3, &h723b72db, &h5470546c
    ! DD  &h29ca294c, &hf0e3f035, &h088508fe, &hc6cbc617, &hf311f34f, &h8cd08ce4, &ha493a459, &hcab8ca96
    ! DD  &h68a6683b, &hb883b84d, &h38203828, &he5ffe52e, &had9fad56, &h0b770b84, &hc8c3c81d, &h99cc99ff
    ! DD  &h580358ed, &h196f199a, &h0e080e0a, &h95bf957e, &h70407050, &hf7e7f730, &h6e2b6ecf, &h1fe21f6e
    ! DD  &hb579b53d, &h090c090f, &h61aa6134, &h57825716, &h9f419f0b, &h9d3a9d80, &h11ea1164, &h25b925cd
    ! DD  &hafe4afdd, &h459a4508, &hdfa4df8d, &ha397a35c, &hea7eead5, &h35da3558, &hed7aedd0, &h431743fc
    ! DD  &hf866f8cb, &hfb94fbb1, &h37a137d3, &hfa1dfa40, &hc23dc268, &hb4f0b4cc, &h32de325d, &h9cb39c71
    ! DD  &h560b56e7, &he372e3da, &h87a78760, &h151c151b, &hf9eff93a, &h63d163bf, &h345334a9, &h9a3e9a85
    ! DD  &hb18fb142, &h7c337cd1, &h8826889b, &h3d5f3da6, &ha1eca1d7, &he476e4df, &h812a8194, &h91499101
    ! DD  &h0f810ffb, &hee88eeaa, &h16ee1661, &hd721d773, &h97c497f5, &ha51aa5a8, &hfeebfe3f, &h6dd96db5
    ! DD  &h78c578ae, &hc539c56d, &h1d991de5, &h76cd76a4, &h3ead3edc, &hcb31cb67, &hb68bb647, &hef01ef5b
    ! DD  &h1218121e, &h602360c5, &h6add6ab0, &h4d1f4df6, &hce4ecee9, &hde2dde7c, &h55f9559d, &h7e487e5a
    ! DD  &h214f21b2, &h03f2037a, &ha065a026, &h5e8e5e19, &h5a785a66, &h655c654b, &h6258624e, &hfd19fd45
    ! DD  &h068d06f4, &h40e54086, &hf298f2be, &h335733ac, &h17671790, &h057f058e, &he805e85e, &h4f644f7d
    ! DD  &h89af896a, &h10631095, &h74b6742f, &h0afe0a75, &h5cf55c92, &h9bb79b74, &h2d3c2d33, &h30a530d6
    ! DD  &h2ece2e49, &h49e94989, &h46684672, &h77447755, &ha8e0a8d8, &h964d9604, &h284328bd, &ha969a929
    ! DD  &hd929d979, &h862e8691, &hd1acd187, &hf415f44a, &h8d598d15, &hd6a8d682, &hb90ab9bc, &h429e420d
    ! DD  &hf66ef6c1, &h2f472fb8, &hdddfdd06, &h23342339, &hcc35cc62, &hf16af1c4, &hc1cfc112, &h85dc85eb
    ! DD  &h8f228f9e, &h71c971a1, &h90c090f0, &haa9baa53, &h018901f1, &h8bd48be1, &h4eed4e8c, &h8eab8e6f
    ! DD  &hab12aba2, &h6fa26f3e, &he60de654, &hdb52dbf2, &h92bb927b, &hb702b7b6, &h692f69ca, &h39a939d9
    ! DD  &hd3d7d30c, &ha761a723, &ha21ea2ad, &hc3b4c399, &h6c506c44, &h07040705, &h04f6047f, &h27c22746
    ! DD  &hac16aca7, &hd025d076, &h50865013, &hdc56dcf7, &h8455841a, &he109e151, &h7abe7a25, &h139113ef
    ' idx3:
    ! DD  &hd939a9d9, &h90176790, &h719cb371, &hd2a6e8d2, &h05070405, &h9852fd98, &h6580a365, &hdfe476df
    ! DD  &h08459a08, &h024b9202, &ha0e080a0, &h665a7866, &hddafe4dd, &hb06addb0, &hbf63d1bf, &h362a3836
    ! DD  &h54e60d54, &h4320c643, &h62cc3562, &hbef298be, &h1e12181e, &h24ebf724, &hd7a1ecd7, &h77416c77
    ! DD  &hbd2843bd, &h32bc7532, &hd47b37d4, &h9b88269b, &h700dfa70, &hf94413f9, &hb1fb94b1, &h5a7e485a
    ! DD  &h7a03f27a, &he48cd0e4, &h47b68b47, &h3c24303c, &ha5e784a5, &h416b5441, &h06dddf06, &hc56023c5
    ! DD  &h45fd1945, &ha33a5ba3, &h68c23d68, &h158d5915, &h21ecf321, &h3166ae31, &h3e6fa23e, &h16578216
    ! DD  &h95106395, &h5bef015b, &h4db8834d, &h91862e91, &hb56dd9b5, &h1f83511f, &h53aa9b53, &h635d7c63
    ! DD  &h3b68a63b, &h3ffeeb3f, &hd630a5d6, &h257abe25, &ha7ac16a7, &h0f090c0f, &h35f0e335, &h23a76123
    ! DD  &hf090c0f0, &hafe98caf, &h809d3a80, &h925cf592, &h810c7381, &h27312c27, &h76d02576, &he7560be7
    ! DD  &h7b92bb7b, &he9ce4ee9, &hf10189f1, &h9f1e6b9f, &ha93453a9, &hc4f16ac4, &h99c3b499, &h975bf197
    ! DD  &h8347e183, &h6b18e66b, &hc822bdc8, &h0e98450e, &h6e1fe26e, &hc9b3f4c9, &h2f74b62f, &hcbf866cb
    ! DD  &hff99ccff, &hea1495ea, &hed5803ed, &hf7dc56f7, &he18bd4e1, &h1b151c1b, &hada21ead, &h0cd3d70c
    ! DD  &h2be2fb2b, &h1dc8c31d, &h195e8e19, &hc22cb5c2, &h8949e989, &h12c1cf12, &h7e95bf7e, &h207dba20
    ! DD  &h6411ea64, &h840b7784, &h6dc5396d, &h6a89af6a, &hd17c33d1, &ha171c9a1, &hceff62ce, &h37bb7137
    ! DD  &hfb0f81fb, &h3db5793d, &h51e10951, &hdc3eaddc, &h2d3f242d, &ha476cda4, &h9d55f99d, &hee82d8ee
    ! DD  &h8640e586, &hae78c5ae, &hcd25b9cd, &h04964d04, &h55774455, &h0a0e080a, &h13508613, &h30f7e730
    ! DD  &hd337a1d3, &h40fa1d40, &h3461aa34, &h8c4eed8c, &hb3b006b3, &h6c54706c, &h2a73b22a, &h523bd252
    ! DD  &h0b9f410b, &h8b027b8b, &h88d8a088, &h4ff3114f, &h67cb3167, &h4627c246, &hc06727c0, &hb4fc90b4
    ! DD  &h28382028, &h7f04f67f, &h78486078, &h2ee5ff2e, &h074c9607, &h4b655c4b, &hc72bb1c7, &h6f8eab6f
    ! DD  &h0d429e0d, &hbbf59cbb, &hf2db52f2, &hf34a1bf3, &ha63d5fa6, &h59a49359, &hbcb90abc, &h3af9ef3a
    ! DD  &hef1391ef, &hfe0885fe, &h01914901, &h6116ee61, &h7cde2d7c, &hb2214fb2, &h42b18f42, &hdb723bdb
    ! DD  &hb82f47b8, &h48bf8748, &h2cae6d2c, &he3c046e3, &h573cd657, &h859a3e85, &h29a96929, &h7d4f647d
    ! DD  &h94812a94, &h492ece49, &h17c6cb17, &hca692fca, &hc3bdfcc3, &h5ca3975c, &h5ee8055e, &hd0ed7ad0
    ! DD  &h87d1ac87, &h8e057f8e, &hba64d5ba, &ha8a51aa8, &hb7264bb7, &hb9be0eb9, &h6087a760, &hf8d55af8
    ! DD  &h22362822, &h111b1411, &hde753fde, &h79d92979, &haaee88aa, &h332d3c33, &h5f794c5f, &hb6b702b6
    ! DD  &h96cab896, &h5835da58, &h9cc4b09c, &hfc4317fc, &h1a84551a, &hf64d1ff6, &h1c598a1c, &h38b27d38
    ! DD  &hac3357ac, &h18cfc718, &hf4068df4, &h69537469, &h749bb774, &hf597c4f5, &h56ad9f56, &hdae372da
    ! DD  &hd5ea7ed5, &h4af4154a, &h9e8f229e, &ha2ab12a2, &h4e62584e, &he85f07e8, &he51d99e5, &h39233439
    ! DD  &hc1f66ec1, &h446c5044, &h5d32de5d, &h72466872, &h26a06526, &h93cdbc93, &h03dadb03, &hc6baf8c6
    ! DD  &hfa9ec8fa, &h82d6a882, &hcf6e2bcf, &h50704050, &heb85dceb, &h750afe75, &h8a93328a, &h8ddfa48d
    ! DD  &h4c29ca4c, &h141c1014, &h73d72173, &hccb4f0cc, &h09d4d309, &h108a5d10, &he2510fe2, &h00000000
    ! DD  &h9a196f9a, &he01a9de0, &h8f94368f, &he6c742e6, &hecc94aec, &hfdd25efd, &hab7fc1ab, &hd8a8e0d8
    #ENDIF   '%def(%MAKE_TABLES)
    END FUNCTION
       
    #IF %def(%MAKE_TABLES)
    '====================
    FUNCTION QP(BYVAL N&, BYVAL X?)
    LOCAL a0?, a1?, a2?, a3?, a4?, b0?, b1?, b2?, b3?, b4?, shl_ret&, shr_ret&
    LOCAL ror4 AS BYTE PTR, ashx AS BYTE PTR
    LOCAL qt0 AS BYTE PTR, qt1 AS BYTE PTR, qt2 AS BYTE PTR, qt3 AS BYTE PTR
       
    ror4 = codeptr(ror_4) : ashx = codeptr(ash_x)
    qt0 = codeptr(qt_0) : qt1 = codeptr(qt_1) : qt2 = codeptr(qt_2) : qt3 = codeptr(qt_3)
       
    a0 = shiftrc(X?,4)            : b0 = X? AND 15
    a1 = a0 XOR b0                : b1 = @ror4[b0] XOR @ashx[a0]
    a2 = @qt0[a1 of 15,N& of 15]  : b2 = @qt1[b1 of 15,N& of 15]
    a3 = a2 XOR b2                : b3 = @ror4[b2] XOR @ashx[a2]
    a4 = @qt2[a3 of 15,N& of 15]  : b4 = @qt3[b3 of 15,N& of 15]
    function = shiftlc(b4,4) OR a4
    exit function
    ror_4:
    !DB   0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
    ash_x:
    !DB   0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7
    qt_0: '(16,2)
    !DB   8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4
    !DB   2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5
    qt_1:  '(16,2)
    !DB   14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13
    !DB   1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8
    qt_2:  '(16,2)
    !DB   11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1
    !DB   4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15
    qt_3:  '(16,2)
    !DB   13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10  
    !DB   11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10
    END FUNCTION
       
    '====================
    FUNCTION Make_QTables&()
    STATIC qbuffer$
    LOCAL i&, qq_0 AS BYTE PTR, qq_1 AS BYTE PTR
    qbuffer = zbs(256*2) : qq_0 = strptr(qbuffer) : qq_1 = qq_0+256
    for i = 0 to 255
       @qq_0[i] = QP(0,(i AND &hff)) : @qq_1[i] = QP(1,(i AND &hff))
    next i
    function = qq_0
    END FUNCTION
       
    '--------------------
    MACRO FUNCTION ffm_5b(x)
    t0 = x
    t1 = x
    !shr t1, 2
    END MACRO = (t0 XOR t1 XOR @tab_5b[x AND 3])
    '--------------------
    MACRO FUNCTION ffm_ef(x)
    t0 = x
    !shr t0, 1
    t1 = x
    !shr t1, 2
    END MACRO = (x XOR t0 XOR t1 XOR @tab_ef[x AND 3])
       
    '====================
    FUNCTION Make_MDSTables&()
    STATIC mdsbuffer$
    LOCAL i&, t0&, t1&, t2&, retval&, shl_ret&, m AS LONG PTR
    LOCAL f01&, f5b&, fef&, tab_5b AS LONG PTR, tab_ef AS LONG PTR
       
    mdsbuffer = zbs(256*4*4) : m = strptr(mdsbuffer)
    tab_5b = codeptr(table_5b) : tab_ef = codeptr(table_ef)
    for i = 0 to 255
       f01 = QP(1,i)       : f5b = ffm_5b(f01)    : fef = ffm_ef(f01)
       t0 = shiftlc(f5b,8) : t1 = shiftlc(fef,16) : t2 = shiftlc(fef,24)
       @m[i of 255,idx0]   = f01 + t0 + t1 + t2
       t0 = shiftlc(fef,8) : t1 = shiftlc(f01,16) : t2 = shiftlc(fef,24)
       @m[i of 255,idx2]   = f5b + t0 + t1 + t2
       
       f01 = QP(0,i)       : f5b = ffm_5b(f01)    : fef = ffm_ef(f01)
       t0 = shiftlc(fef,8) : t1 = shiftlc(f5b,16) : t2 = shiftlc(f01,24)
       @m[i of 255,idx1]   = fef + t0 + t1 + t2
       t0 = shiftlc(f01,8) : t1 = shiftlc(fef,16) : t2 = shiftlc(f5b,24)
       @m[i of 255,idx3]   = f5b + t0 + t1 + t2
    next i
    function = m
    exit function
    table_5b:
    !DD   &h00000000, &h0000005A, &h000000B4, &h000000EE
    table_ef:
    !DD   &h00000000, &h000000EE, &h000000B4, &h0000005A
    END FUNCTION
    #ENDIF
    '-- end TWOFISH.BAS
       
       
    '=====================================================================
    '                       Twofish Test Bed code
    '               Compiles with either PBWIN 7.0+ or PBCC 3.0+
    '=====================================================================
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    '============
    DEFLNG A-Z
    %USEMACROS = 1
    #INCLUDE "WIN32API.INC"
       
    '--------------------
    '-- Utility macros
    '--------------------
       
    #IF %def(%pb_win32)
       MACRO eol=$CR
       MACRO mbox(t)=msgbox t
    #ELSEIF %def(%pb_cc32)
       MACRO eol=$CRLF
       MACRO mbox(t)=stdout t
    #ENDIF
       
    '--------------------
    MACRO EnterCC
    #IF %def(%pb_cc32)
       LOCAL launched&
       if (cursory = 1) and (cursorx = 1) then launched = -1
    #ENDIF
    END MACRO
       
    '--------------------
    MACRO ExitCC
    #IF %def(%pb_cc32)
       if launched then
          input flush
          stdout "Press any key to end"
          waitkey$
       end if
    #ENDIF 
    END MACRO
       
    '--------------------  
    'MACRO zbs(x)=string$(x,0) 'also defined in TWOFISH.BAS
       
    '--------------------
    MACRO hex8(x)=hex$(x,8)+"h"
       
    #INCLUDE "TWOFISH.BAS"
    DECLARE FUNCTION Hex2Show$(Buffer$)
       
    '====================
    FUNCTION PBMain&()
    REGISTER i&
    LOCAL key$, plain$, cipher$, shouldbe$, t$
    LOCAL ctx AS TWOFISH_CONTEXT  ' defined in TWOFISH.BAS
    EnterCC
       
    '-- Standard Twofish test vectors (from ECB_IVAL.TXT)
    '-- 128-bit key
    key$     = chr$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
    plain    = chr$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h9F,&h58,&h9F,&h5C,&hF6,&h12,&h2C,&h32,&hB6,&hBF,&hEC,&h2F,&h2A,&hE8,&hC3,&h5A)
    t =     "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
       
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key$     = chr$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    '-- 192-bit key
    key      = chr$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                    &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77)
    plain    = chr$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&hCF,&hD1,&hD2,&hE5,&hA9,&hBE,&h9C,&hDF,&h50,&h1F,&h13,&hB8,&h92,&hBD,&h22,&h48)
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
       
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                    &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    '-- 256-bit key
    key      = chr$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                    &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&hAA,&hBB,&hCC,&hDD,&hEE,&hFF)
    plain    = chr$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h37,&h52,&h7B,&hE0,&h05,&h23,&h34,&hB8,&h9F,&h0C,&hFC,&hCA,&hE8,&h7C,&hFA,&h20)
       
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                    &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&hAA,&hBB,&hCC,&hDD,&hEE,&hFF)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
    mbox(t)
       
    Done:
    ExitCC
    exit function
       
    '============
    DoEncrypt:
    ctx.action        = %ENCRYPT
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(plain)
    ctx.OutBlock      = strptr(cipher)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain)\%BLOCKSIZE)  '<-- Required: (len(plain$) mod 16) = 0
          EncryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i&
    else
       mbox("DoEncrypt SetKey Error")
    end if
    '-- Burn the subkey
    if Ctx.S_Box then ZeroMemory(Ctx.S_Box,sizeof(Ctx.S_Box_Buffer))
    if Ctx.XKey  then ZeroMemory(Ctx.XKey, sizeof(Ctx.XKey_Buffer))
    RETURN
       
    '============
    DoDecrypt:
    ctx.action        = %DECRYPT
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(cipher)
    ctx.OutBlock      = strptr(plain)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain$)\%BLOCKSIZE)  '<-- Required: (len(plain$) mod 16) = 0
          DecryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i
    else
       mbox("DoDecrypt SetKey Error")
    end if
    '-- Burn the subkey
    if Ctx.S_Box then ZeroMemory(Ctx.S_Box,sizeof(Ctx.S_Box_Buffer))
    if Ctx.XKey  then ZeroMemory(Ctx.XKey, sizeof(Ctx.XKey_Buffer))
    RETURN
    END FUNCTION
       
       
    '====================
    FUNCTION Hex2Show$(Buffer$)
    REGISTER i&
    LOCAL t$, b AS BYTE PTR
    b = strptr(Buffer$)
    for i = 0 to len(Buffer$)-1
       t = t + hex$(@b[i],2) + " "
    next i
    function = t
    END FUNCTION
    '-- end TESTBED.BAS

    [This message has been edited by Greg Turgeon (edited July 07, 2003).]
Working...
X