Twofish
Algorithm creator(s)
Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson
PB author(s)
Greg Turgeon
Description
Twofish is a 128-bit block cipher that accepts a variable-length key up to 256 bits. The cipher is a 16-round Feistel network with a bijective F function made up of four key-dependent 8-by-8-bit S-boxes, a fixed 4-by-4 maximum distance separable matrix over GF(28), a pseudo-Hadamard transform, bitwise rotations, and a carefully designed key schedule. A fully optimized implementation of Twofish encrypts on a Pentium Pro at 17.8 clock cycles per byte, and an 8-bit smart card implementation encrypts at 1820 clock cycles per byte. Twofish can be implemented in hardware in 14000 gates. The design of both the round function and the key schedule permits a wide variety of tradeoffs between speed, software size, key setup time, gate count, and memory.
Note
The Twofish algorithm is unpatented, uncopyrighted, and free for any use public or private, commercial or non-commercial.
Source
http://www.powerbasic.com/support/pbforums/showthread.php?t=23914
See also
Source Code
Download source code file twofish.bas (Right-click -> "Save as ...")
'This file contains two source code files.
'TWOFISH.INC is at the start, and a calling
'demo (TESTBED.BAS) is at the end.
'
'
'Start of TWOFISH.INC
#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.INC file
contents. ALL code compiles WITH (AND requires) either PBCC 3.0+ OR
PBWIN 7.0+.
Implementation Notes
-- 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, who tested 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.INC
'
'
'
'
'
'
'#####################################################################
'
'
'
'
'
'
'=====================================================================
' 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.INC
'--------------------
MACRO hex8(x)=HEX$(x,8)+"h"
#INCLUDE "TWOFISH.INC"
DECLARE FUNCTION Hex2Show$(Buffer$)
'====================
FUNCTION PBMAIN&()
REGISTER i&
LOCAL key$, plain$, cipher$, shouldbe$, t$
LOCAL ctx AS TWOFISH_CONTEXT ' defined in TWOFISH.INC
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