1 /**
2 * Serpent in x86-32 asm
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.block.serp_x86_32;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_SERPENT_X86_32):
15 
16 import botan.block.serpent;
17 import botan.utils.loadstor;
18 import botan.utils.asm_x86_32.asm_x86_32;
19 import botan.block.block_cipher;
20 import botan.utils.mem_ops;
21 
22 /**
23 * Serpent implementation in x86-32 assembly
24 */
25 final class Serpent_X86_32 : Serpent
26 {
27 public:
28     /*
29     * Serpent Encryption
30     */
31     override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks)
32     {
33         auto keys = this.getRoundKeys().ptr;
34         
35         foreach (size_t i; 0 .. blocks)
36         {
37             botan_serpent_x86_32_encrypt(input, output, keys);
38             input += BLOCK_SIZE;
39             output += BLOCK_SIZE;
40         }
41     }
42     /*
43     * Serpent Decryption
44     */
45     override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks)
46     {
47         auto keys = this.getRoundKeys().ptr;
48         
49         foreach (size_t i; 0 .. blocks)
50         {
51             botan_serpent_x86_32_decrypt(input, output, keys);
52             input += BLOCK_SIZE;
53             output += BLOCK_SIZE;
54         }
55     }
56 
57     override @property size_t parallelism() const { return 1; }
58     override BlockCipher clone() const { return new Serpent_X86_32; }
59 protected:
60     /*
61     * Serpent Key Schedule
62     */
63     override void keySchedule(const(ubyte)* key, size_t length)
64     {
65         SecureVector!uint W = SecureVector!uint(140);
66         foreach (size_t i; 0 .. (length / 4))
67             W[i] = loadLittleEndian!uint(key, i);
68         W[length / 4] |= uint(1) << ((length%4)*8);
69         
70         botan_serpent_x86_32_key_schedule(W.ptr);
71         this.setRoundKeys(*cast(uint[132]*) &W[8]);
72     }
73 
74 }
75 
76 /**
77 * Entry point for Serpent encryption in x86 asm
78 * Params:
79 *  input = the input block
80 *  output = the output block
81 *  ks = the key schedule
82 */
83 extern(C)
84 void botan_serpent_x86_32_encrypt(const(ubyte)* input, ubyte* output, in uint* ks ) pure
85 {
86 
87     enum PUSHED = 4;
88     enum ASM = START_ASM ~
89           "naked;\n" ~
90           SPILL_REGS() ~
91           ASSIGN(EBP, ARG(PUSHED, 1)) /* input block */ ~
92           ASSIGN(EAX, ARRAY4(EBP, 0)) ~
93           ASSIGN(EBX, ARRAY4(EBP, 1)) ~
94           ASSIGN(ECX, ARRAY4(EBP, 2)) ~
95           ASSIGN(EDX, ARRAY4(EBP, 3)) ~
96           
97           ASSIGN(EDI, ARG(PUSHED, 3))  ~ /* round keys */
98           ZEROIZE(EBP) ~
99           
100           E_ROUND!SBOX_E1(EAX, EBX, ECX, EDX, EBP,  0 ) ~
101           E_ROUND!SBOX_E2(EAX, EBX, ECX, EDX, EBP,  1 ) ~
102           E_ROUND!SBOX_E3(EAX, EBX, ECX, EDX, EBP,  2 ) ~
103           E_ROUND!SBOX_E4(EAX, EBX, ECX, EDX, EBP,  3 ) ~
104           E_ROUND!SBOX_E5(EAX, EBX, ECX, EDX, EBP,  4 ) ~
105           E_ROUND!SBOX_E6(EAX, EBX, ECX, EDX, EBP,  5 ) ~
106           E_ROUND!SBOX_E7(EAX, EBX, ECX, EDX, EBP,  6 ) ~
107           E_ROUND!SBOX_E8(EAX, EBX, ECX, EDX, EBP,  7 ) ~
108           
109           E_ROUND!SBOX_E1(EAX, EBX, ECX, EDX, EBP,  8 ) ~
110           E_ROUND!SBOX_E2(EAX, EBX, ECX, EDX, EBP,  9 ) ~
111           E_ROUND!SBOX_E3(EAX, EBX, ECX, EDX, EBP, 10 ) ~
112           E_ROUND!SBOX_E4(EAX, EBX, ECX, EDX, EBP, 11 ) ~
113           E_ROUND!SBOX_E5(EAX, EBX, ECX, EDX, EBP, 12 ) ~
114           E_ROUND!SBOX_E6(EAX, EBX, ECX, EDX, EBP, 13 ) ~
115           E_ROUND!SBOX_E7(EAX, EBX, ECX, EDX, EBP, 14 ) ~
116           E_ROUND!SBOX_E8(EAX, EBX, ECX, EDX, EBP, 15 ) ~
117           
118           E_ROUND!SBOX_E1(EAX, EBX, ECX, EDX, EBP, 16 ) ~
119           E_ROUND!SBOX_E2(EAX, EBX, ECX, EDX, EBP, 17 ) ~
120           E_ROUND!SBOX_E3(EAX, EBX, ECX, EDX, EBP, 18 ) ~
121           E_ROUND!SBOX_E4(EAX, EBX, ECX, EDX, EBP, 19 ) ~
122           E_ROUND!SBOX_E5(EAX, EBX, ECX, EDX, EBP, 20 ) ~
123           E_ROUND!SBOX_E6(EAX, EBX, ECX, EDX, EBP, 21 ) ~
124           E_ROUND!SBOX_E7(EAX, EBX, ECX, EDX, EBP, 22 ) ~
125           E_ROUND!SBOX_E8(EAX, EBX, ECX, EDX, EBP, 23 ) ~
126           
127           E_ROUND!SBOX_E1(EAX, EBX, ECX, EDX, EBP, 24 ) ~
128           E_ROUND!SBOX_E2(EAX, EBX, ECX, EDX, EBP, 25 ) ~
129           E_ROUND!SBOX_E3(EAX, EBX, ECX, EDX, EBP, 26 ) ~
130           E_ROUND!SBOX_E4(EAX, EBX, ECX, EDX, EBP, 27 ) ~
131           E_ROUND!SBOX_E5(EAX, EBX, ECX, EDX, EBP, 28 ) ~
132           E_ROUND!SBOX_E6(EAX, EBX, ECX, EDX, EBP, 29 ) ~
133           E_ROUND!SBOX_E7(EAX, EBX, ECX, EDX, EBP, 30 ) ~
134           
135           KEY_XOR(EAX, EBX, ECX, EDX, 31) ~
136           SBOX_E8(EAX, EBX, ECX, EDX, EBP) ~
137           KEY_XOR(EAX, EBX, ECX, EDX, 32) ~
138           
139           ASSIGN(EBP, ARG(PUSHED, 2)) /* output block */ ~
140           ASSIGN(ARRAY4(EBP, 0), EAX) ~
141           ASSIGN(ARRAY4(EBP, 1), EBX) ~
142           ASSIGN(ARRAY4(EBP, 2), ECX) ~
143           ASSIGN(ARRAY4(EBP, 3), EDX) ~
144           RESTORE_REGS() ~
145           "ret;\n" ~
146           END_ASM;
147     mixin(ASM);
148 }
149 
150 /**
151 * Entry point for Serpent decryption in x86 asm
152 * Params:
153 *  input = the input block
154 *  output = the output block
155 *  ks = the key schedule
156 */
157 extern(C)
158 void botan_serpent_x86_32_decrypt(const(ubyte)* input, ubyte* output, in uint* ks) pure
159 {
160 
161     enum PUSHED = 4;
162     
163     enum ASM = START_ASM ~
164           "naked;" ~
165           SPILL_REGS() ~ 
166           ASSIGN(EBP, ARG(PUSHED, 1)) ~ /* input block */
167           ASSIGN(EAX, ARRAY4(EBP, 0)) ~
168           ASSIGN(EBX, ARRAY4(EBP, 1)) ~ 
169           ASSIGN(ECX, ARRAY4(EBP, 2)) ~
170           ASSIGN(EDX, ARRAY4(EBP, 3)) ~
171           
172           ASSIGN(EDI, ARG(PUSHED, 3)) ~ /* round keys */
173           
174           ZEROIZE(EBP) ~
175           
176           KEY_XOR(EAX, EBX, ECX, EDX, 32) ~
177           SBOX_D8(EAX, EBX, ECX, EDX, EBP) ~
178           KEY_XOR(EAX, EBX, ECX, EDX, 31) ~
179           
180           D_ROUND!SBOX_D7(EAX, EBX, ECX, EDX, EBP, 30) ~
181           D_ROUND!SBOX_D6(EAX, EBX, ECX, EDX, EBP, 29) ~
182           D_ROUND!SBOX_D5(EAX, EBX, ECX, EDX, EBP, 28) ~
183           D_ROUND!SBOX_D4(EAX, EBX, ECX, EDX, EBP, 27) ~
184           D_ROUND!SBOX_D3(EAX, EBX, ECX, EDX, EBP, 26) ~
185           D_ROUND!SBOX_D2(EAX, EBX, ECX, EDX, EBP, 25) ~
186           D_ROUND!SBOX_D1(EAX, EBX, ECX, EDX, EBP, 24) ~
187           
188           D_ROUND!SBOX_D8(EAX, EBX, ECX, EDX, EBP, 23) ~
189           D_ROUND!SBOX_D7(EAX, EBX, ECX, EDX, EBP, 22) ~
190           D_ROUND!SBOX_D6(EAX, EBX, ECX, EDX, EBP, 21) ~
191           D_ROUND!SBOX_D5(EAX, EBX, ECX, EDX, EBP, 20) ~
192           D_ROUND!SBOX_D4(EAX, EBX, ECX, EDX, EBP, 19) ~
193           D_ROUND!SBOX_D3(EAX, EBX, ECX, EDX, EBP, 18) ~
194           D_ROUND!SBOX_D2(EAX, EBX, ECX, EDX, EBP, 17) ~
195           D_ROUND!SBOX_D1(EAX, EBX, ECX, EDX, EBP, 16) ~
196           
197           D_ROUND!SBOX_D8(EAX, EBX, ECX, EDX, EBP, 15) ~
198           D_ROUND!SBOX_D7(EAX, EBX, ECX, EDX, EBP, 14) ~
199           D_ROUND!SBOX_D6(EAX, EBX, ECX, EDX, EBP, 13) ~
200           D_ROUND!SBOX_D5(EAX, EBX, ECX, EDX, EBP, 12) ~
201           D_ROUND!SBOX_D4(EAX, EBX, ECX, EDX, EBP, 11) ~
202           D_ROUND!SBOX_D3(EAX, EBX, ECX, EDX, EBP, 10) ~
203           D_ROUND!SBOX_D2(EAX, EBX, ECX, EDX, EBP,  9) ~
204           D_ROUND!SBOX_D1(EAX, EBX, ECX, EDX, EBP,  8) ~
205           
206           D_ROUND!SBOX_D8(EAX, EBX, ECX, EDX, EBP,  7) ~
207           D_ROUND!SBOX_D7(EAX, EBX, ECX, EDX, EBP,  6) ~
208           D_ROUND!SBOX_D6(EAX, EBX, ECX, EDX, EBP,  5) ~
209           D_ROUND!SBOX_D5(EAX, EBX, ECX, EDX, EBP,  4) ~
210           D_ROUND!SBOX_D4(EAX, EBX, ECX, EDX, EBP,  3) ~
211           D_ROUND!SBOX_D3(EAX, EBX, ECX, EDX, EBP,  2) ~
212           D_ROUND!SBOX_D2(EAX, EBX, ECX, EDX, EBP,  1) ~
213           D_ROUND!SBOX_D1(EAX, EBX, ECX, EDX, EBP,  0) ~
214           
215           ASSIGN(EBP, ARG(PUSHED, 2)) ~ /* output block */
216           ASSIGN(ARRAY4(EBP, 0), EAX) ~
217           ASSIGN(ARRAY4(EBP, 1), EBX) ~
218           ASSIGN(ARRAY4(EBP, 2), ECX) ~
219           ASSIGN(ARRAY4(EBP, 3), EDX) ~
220           RESTORE_REGS() ~ 
221           "ret;\n" ~
222           END_ASM;
223     mixin(ASM);
224 }
225 
226 /**
227 * Entry point for Serpent key schedule in x86 asm
228 * Params:
229 *  ks = holds the initial working key (padded), and is set to the
230             final key schedule
231 */
232 extern(C)
233 void botan_serpent_x86_32_key_schedule(uint* ks) pure
234 {
235     string LOAD_AND_SBOX(alias SBOX)(ubyte MSG) {
236         return  ASSIGN(EAX, ARRAY4(EDI, (4*MSG+ 8))) ~
237                 ASSIGN(EBX, ARRAY4(EDI, (4*MSG+ 9))) ~
238                 ASSIGN(ECX, ARRAY4(EDI, (4*MSG+10))) ~
239                 ASSIGN(EDX, ARRAY4(EDI, (4*MSG+11))) ~
240                 SBOX(EAX, EBX, ECX, EDX, EBP)        ~
241                 ASSIGN(ARRAY4(EDI, (4*MSG+ 8)), EAX) ~
242                 ASSIGN(ARRAY4(EDI, (4*MSG+ 9)), EBX) ~ 
243                 ASSIGN(ARRAY4(EDI, (4*MSG+10)), ECX) ~ 
244                 ASSIGN(ARRAY4(EDI, (4*MSG+11)), EDX);
245     }
246     enum PUSHED = 4;
247     enum ASM =
248           START_ASM ~
249           "naked;\n" ~
250           SPILL_REGS() ~
251           ASSIGN(EDI, ARG(PUSHED, 1)) ~ /* round keys */
252           ASSIGN(ESI, IMM(8)) ~
253           ADD_IMM(EDI, 32) ~
254           
255           START_LOOP("L_SERP_EXPANSION") ~
256           ASSIGN(EAX, ARRAY4(EDI, -1)) ~
257           ASSIGN(EBX, ARRAY4(EDI, -3)) ~
258           ASSIGN(ECX, ARRAY4(EDI, -5)) ~
259           ASSIGN(EDX, ARRAY4(EDI, -8)) ~
260           
261           ASSIGN(EBP, ESI) ~
262           SUB_IMM(EBP, 8) ~
263           XOR(EBP, IMM(0x9E3779B9)) ~
264           XOR(EAX, EBX) ~
265           XOR(ECX, EDX) ~
266           XOR(EAX, EBP) ~
267           XOR(EAX, ECX) ~
268           
269           ROTL_IMM(EAX, 11) ~
270           
271           ASSIGN(ARRAY4(EDI, 0), EAX) ~
272           
273           ADD_IMM(ESI, 1) ~
274           ADD_IMM(EDI, 4) ~
275           LOOP_UNTIL_EQ(ESI, 140, "L_SERP_EXPANSION") ~
276           
277           ASSIGN(EDI, ARG(PUSHED, 1)) ~ /* round keys */
278           
279           LOAD_AND_SBOX!SBOX_E4( 0 ) ~
280           LOAD_AND_SBOX!SBOX_E3( 1 ) ~
281           LOAD_AND_SBOX!SBOX_E2( 2 ) ~
282           LOAD_AND_SBOX!SBOX_E1( 3 ) ~
283           
284           LOAD_AND_SBOX!SBOX_E8( 4 ) ~
285           LOAD_AND_SBOX!SBOX_E7( 5 ) ~
286           LOAD_AND_SBOX!SBOX_E6( 6 ) ~
287           LOAD_AND_SBOX!SBOX_E5( 7 ) ~
288           LOAD_AND_SBOX!SBOX_E4( 8 ) ~
289           LOAD_AND_SBOX!SBOX_E3( 9 ) ~
290           LOAD_AND_SBOX!SBOX_E2(10 ) ~
291           LOAD_AND_SBOX!SBOX_E1(11 ) ~
292           
293           LOAD_AND_SBOX!SBOX_E8(12 ) ~
294           LOAD_AND_SBOX!SBOX_E7(13 ) ~
295           LOAD_AND_SBOX!SBOX_E6(14 ) ~
296           LOAD_AND_SBOX!SBOX_E5(15 ) ~
297           LOAD_AND_SBOX!SBOX_E4(16 ) ~
298           LOAD_AND_SBOX!SBOX_E3(17 ) ~
299           LOAD_AND_SBOX!SBOX_E2(18 ) ~
300           LOAD_AND_SBOX!SBOX_E1(19 ) ~
301           
302           LOAD_AND_SBOX!SBOX_E8(20 ) ~
303           LOAD_AND_SBOX!SBOX_E7(21 ) ~
304           LOAD_AND_SBOX!SBOX_E6(22 ) ~
305           LOAD_AND_SBOX!SBOX_E5(23 ) ~
306           LOAD_AND_SBOX!SBOX_E4(24 ) ~
307           LOAD_AND_SBOX!SBOX_E3(25 ) ~
308           LOAD_AND_SBOX!SBOX_E2(26 ) ~
309           LOAD_AND_SBOX!SBOX_E1(27 ) ~
310           
311           LOAD_AND_SBOX!SBOX_E8(28 ) ~
312           LOAD_AND_SBOX!SBOX_E7(29 ) ~
313           LOAD_AND_SBOX!SBOX_E6(30 ) ~
314           LOAD_AND_SBOX!SBOX_E5(31 ) ~
315           LOAD_AND_SBOX!SBOX_E4(32 ) ~
316 
317           RESTORE_REGS() ~
318           "ret;\n"~
319           END_ASM;
320 
321     mixin(ASM);
322 }
323 
324 string E_ROUND(alias SBOX)(string A, string B, string C, string D, string T, ubyte N) 
325 {
326     return  KEY_XOR(A, B, C, D, N) ~
327             SBOX(A, B, C, D, T)     ~
328             TRANSFORM(A, B, C, D, T);
329 }
330 
331 string D_ROUND(alias SBOX)(string A, string B, string C, string D, string T, ubyte N)
332 {
333     return  I_TRANSFORM(A, B, C, D, T) ~
334             SBOX(A, B, C, D, T) ~
335             KEY_XOR(A, B, C, D, N);
336 }
337 
338 string KEY_XOR(string A, string B, string C, string D, ubyte N) {
339     return  XOR(A, ARRAY4(EDI, (4*N  )))  ~
340             XOR(B, ARRAY4(EDI, (4*N+1)))  ~
341             XOR(C, ARRAY4(EDI, (4*N+2)))  ~
342             XOR(D, ARRAY4(EDI, (4*N+3)));
343 }
344 
345 string TRANSFORM(string A, string B, string C, string D, string T) {
346     return  ROTL_IMM(A, 13)  ~
347             ROTL_IMM(C, 3)   ~
348             SHL2_3(T, A) ~
349             XOR(B, A)    ~
350             XOR(D, C)    ~
351             XOR(B, C)    ~
352             XOR(D, T)    ~
353             ROTL_IMM(B, 1)   ~
354             ROTL_IMM(D, 7)   ~
355             ASSIGN(T, B) ~
356             SHL_IMM(T, 7)~
357             XOR(A, B)    ~
358             XOR(C, D)    ~
359             XOR(A, D)    ~
360             XOR(C, T)    ~
361             ROTL_IMM(A, 5)   ~
362             ROTL_IMM(C, 22);
363 }
364 
365 string I_TRANSFORM(string A, string B, string C, string D, string T) {
366     return  ROTR_IMM(C, 22)  ~
367             ROTR_IMM(A, 5)   ~
368             ASSIGN(T, B) ~
369             SHL_IMM(T, 7)~
370             XOR(A, B)    ~
371             XOR(C, D)    ~
372             XOR(A, D)    ~
373             XOR(C, T)    ~
374             ROTR_IMM(D, 7)   ~
375             ROTR_IMM(B, 1)   ~
376             SHL2_3(T, A) ~
377             XOR(B, C)    ~
378             XOR(D, C)    ~
379             XOR(B, A)    ~
380             XOR(D, T)    ~
381             ROTR_IMM(C, 3)   ~
382             ROTR_IMM(A, 13);
383 }
384 string SBOX_E1(string A, string B, string C, string D, string T)
385 {
386     return  XOR(D, A)    ~
387             ASSIGN(T, B) ~
388             AND(B, D)    ~
389             XOR(T, C)    ~
390             XOR(B, A)    ~
391             OR(A, D)     ~
392             XOR(A, T)    ~
393             XOR(T, D)    ~
394             XOR(D, C)    ~
395             OR(C, B)     ~
396             XOR(C, T)    ~
397             NOT(T)       ~
398             OR(T, B)     ~
399             XOR(B, D)    ~
400             XOR(B, T)    ~
401             OR(D, A)     ~
402             XOR(B, D)    ~
403             XOR(T, D)    ~
404             ASSIGN(D, A) ~
405             ASSIGN(A, B) ~
406             ASSIGN(B, T);
407 }
408 string SBOX_E2(string A, string B, string C, string D, string T) 
409 {
410     return  NOT(A)       ~
411             NOT(C)       ~
412             ASSIGN(T, A) ~
413             AND(A, B)    ~
414             XOR(C, A)    ~
415             OR(A, D)     ~
416             XOR(D, C)    ~
417             XOR(B, A)    ~
418             XOR(A, T)    ~
419             OR(T, B)     ~
420             XOR(B, D)    ~
421             OR(C, A)     ~
422             AND(C, T)    ~
423             XOR(A, B)    ~
424             AND(B, C)    ~
425             XOR(B, A)    ~
426             AND(A, C)    ~
427             XOR(T, A)    ~
428             ASSIGN(A, C) ~
429             ASSIGN(C, D) ~
430             ASSIGN(D, B) ~
431             ASSIGN(B, T);
432 }
433 
434 string SBOX_E3(string A, string B, string C, string D, string T) {
435     return  ASSIGN(T, A) ~
436             AND(A, C)    ~
437             XOR(A, D)    ~
438             XOR(C, B)    ~
439             XOR(C, A)    ~
440             OR(D, T)     ~
441             XOR(D, B)    ~
442             XOR(T, C)    ~
443             ASSIGN(B, D) ~
444             OR(D, T)     ~
445             XOR(D, A)    ~
446             AND(A, B)    ~
447             XOR(T, A)    ~
448             XOR(B, D)    ~
449             XOR(B, T)    ~
450             NOT(T)       ~
451             ASSIGN(A, C) ~
452             ASSIGN(C, B) ~
453             ASSIGN(B, D) ~
454             ASSIGN(D, T);
455 
456 }
457 
458 string SBOX_E4(string A, string B, string C, string D, string T) {
459     return  ASSIGN(T, A) ~
460             OR(A, D)     ~
461             XOR(D, B)    ~
462             AND(B, T)    ~
463             XOR(T, C)    ~
464             XOR(C, D)    ~
465             AND(D, A)    ~
466             OR(T, B)     ~
467             XOR(D, T)    ~
468             XOR(A, B)    ~
469             AND(T, A)    ~
470             XOR(B, D)    ~
471             XOR(T, C)    ~
472             OR(B, A)     ~
473             XOR(B, C)    ~
474             XOR(A, D)    ~
475             ASSIGN(C, B) ~
476             OR(B, D)     ~
477             XOR(B, A)    ~
478             ASSIGN(A, B) ~
479             ASSIGN(B, C) ~
480             ASSIGN(C, D) ~
481             ASSIGN(D, T);
482 }
483 
484 string SBOX_E5(string A, string B, string C, string D, string T) {
485     return  XOR(B, D)    ~
486             NOT(D)       ~
487             XOR(C, D)    ~
488             XOR(D, A)    ~
489             ASSIGN(T, B) ~
490             AND(B, D)    ~
491             XOR(B, C)    ~
492             XOR(T, D)    ~
493             XOR(A, T)    ~
494             AND(C, T)    ~
495             XOR(C, A)    ~
496             AND(A, B)    ~
497             XOR(D, A)    ~
498             OR(T, B)     ~
499             XOR(T, A)    ~
500             OR(A, D)     ~
501             XOR(A, C)    ~
502             AND(C, D)    ~
503             NOT(A)       ~
504             XOR(T, C)    ~
505             ASSIGN(C, A) ~
506             ASSIGN(A, B) ~
507             ASSIGN(B, T);
508 }
509 
510 string SBOX_E6(string A, string B, string C, string D, string T) {
511     return  XOR(A, B)    ~
512             XOR(B, D)    ~
513             NOT(D)       ~
514             ASSIGN(T, B) ~
515             AND(B, A)    ~
516             XOR(C, D)    ~
517             XOR(B, C)    ~
518             OR(C, T)     ~
519             XOR(T, D)    ~
520             AND(D, B)    ~
521             XOR(D, A)    ~
522             XOR(T, B)    ~
523             XOR(T, C)    ~
524             XOR(C, A)    ~
525             AND(A, D)    ~
526             NOT(C)       ~
527             XOR(A, T)    ~
528             OR(T, D)     ~
529             XOR(T, C)    ~
530             ASSIGN(C, A) ~
531             ASSIGN(A, B) ~
532             ASSIGN(B, D) ~
533             ASSIGN(D, T);
534 }
535 
536 string SBOX_E7(string A, string B, string C, string D, string T) {
537     return  NOT(C)       ~
538             ASSIGN(T, D) ~
539             AND(D, A)    ~
540             XOR(A, T)    ~
541             XOR(D, C)    ~
542             OR(C, T)     ~
543             XOR(B, D)    ~
544             XOR(C, A)    ~
545             OR(A, B)     ~
546             XOR(C, B)    ~
547             XOR(T, A)    ~
548             OR(A, D)     ~
549             XOR(A, C)    ~
550             XOR(T, D)    ~
551             XOR(T, A)    ~
552             NOT(D)       ~
553             AND(C, T)    ~
554             XOR(C, D)    ~
555             ASSIGN(D, C) ~
556             ASSIGN(C, T);
557 }
558     
559 string SBOX_E8(string A, string B, string C, string D, string T) {
560     return  ASSIGN(T, B) ~
561             OR(B, C)     ~
562             XOR(B, D)    ~
563             XOR(T, C)    ~
564             XOR(C, B)    ~
565             OR(D, T)     ~
566             AND(D, A)    ~
567             XOR(T, C)    ~
568             XOR(D, B)    ~
569             OR(B, T)     ~
570             XOR(B, A)    ~
571             OR(A, T)     ~
572             XOR(A, C)    ~
573             XOR(B, T)    ~
574             XOR(C, B)    ~
575             AND(B, A)    ~
576             XOR(B, T)    ~
577             NOT(C)       ~
578             OR(C, A)     ~
579             XOR(T, C)    ~
580             ASSIGN(C, B) ~
581             ASSIGN(B, D) ~
582             ASSIGN(D, A) ~
583             ASSIGN(A, T);
584 }
585 
586 string SBOX_D1(string A, string B, string C, string D, string T) {
587     return    NOT(C)       ~
588             ASSIGN(T, B) ~
589             OR(B, A)     ~
590             NOT(T)       ~
591             XOR(B, C)    ~
592             OR(C, T)     ~
593             XOR(B, D)    ~
594             XOR(A, T)    ~
595             XOR(C, A)    ~
596             AND(A, D)    ~
597             XOR(T, A)    ~
598             OR(A, B)     ~
599             XOR(A, C)    ~
600             XOR(D, T)    ~
601             XOR(C, B)    ~
602             XOR(D, A)    ~
603             XOR(D, B)    ~
604             AND(C, D)    ~
605             XOR(T, C)    ~
606             ASSIGN(C, B) ~
607             ASSIGN(B, T);
608 }
609 
610 string SBOX_D2(string A, string B, string C, string D, string T) {
611     return  ASSIGN(T, B) ~
612             XOR(B, D)    ~
613             AND(D, B)    ~
614             XOR(T, C)    ~
615             XOR(D, A)    ~
616             OR(A, B)     ~
617             XOR(C, D)    ~
618             XOR(A, T)    ~
619             OR(A, C)     ~
620             XOR(B, D)    ~
621             XOR(A, B)    ~
622             OR(B, D)     ~
623             XOR(B, A)    ~
624             NOT(T)       ~
625             XOR(T, B)    ~
626             OR(B, A)     ~
627             XOR(B, A)    ~
628             OR(B, T)     ~
629             XOR(D, B)    ~
630             ASSIGN(B, A) ~
631             ASSIGN(A, T) ~
632             ASSIGN(T, D) ~
633             ASSIGN(D, C) ~
634             ASSIGN(C, T);
635 }
636 
637 string SBOX_D3(string A, string B, string C, string D, string T) {
638     return  XOR(C, D)    ~
639             XOR(D, A)    ~
640             ASSIGN(T, D) ~
641             AND(D, C)    ~
642             XOR(D, B)    ~
643             OR(B, C)     ~
644             XOR(B, T)    ~
645             AND(T, D)    ~
646             XOR(C, D)    ~
647             AND(T, A)    ~
648             XOR(T, C)    ~
649             AND(C, B)    ~
650             OR(C, A)     ~
651             NOT(D)       ~
652             XOR(C, D)    ~
653             XOR(A, D)    ~
654             AND(A, B)    ~
655             XOR(D, T)    ~
656             XOR(D, A)    ~
657             ASSIGN(A, B) ~
658             ASSIGN(B, T);
659 }
660 
661 string SBOX_D4(string A, string B, string C, string D, string T) {
662     return  ASSIGN(T, C) ~
663             XOR(C, B)    ~
664             XOR(A, C)    ~
665             AND(T, C)    ~
666             XOR(T, A)    ~
667             AND(A, B)    ~
668             XOR(B, D)    ~
669             OR(D, T)     ~
670             XOR(C, D)    ~
671             XOR(A, D)    ~
672             XOR(B, T)    ~
673             AND(D, C)    ~
674             XOR(D, B)    ~
675             XOR(B, A)    ~
676             OR(B, C)     ~
677             XOR(A, D)    ~
678             XOR(B, T)    ~
679             XOR(A, B)    ~
680             ASSIGN(T, A) ~
681             ASSIGN(A, C) ~
682             ASSIGN(C, D) ~
683             ASSIGN(D, T);
684 
685 }
686 
687 string SBOX_D5(string A, string B, string C, string D, string T) {
688     return  ASSIGN(T, C) ~
689             AND(C, D)    ~
690             XOR(C, B)    ~
691             OR(B, D)     ~
692             AND(B, A)    ~
693             XOR(T, C)    ~
694             XOR(T, B)    ~
695             AND(B, C)    ~
696             NOT(A)       ~
697             XOR(D, T)    ~
698             XOR(B, D)    ~
699             AND(D, A)    ~
700             XOR(D, C)    ~
701             XOR(A, B)    ~
702             AND(C, A)    ~
703             XOR(D, A)    ~
704             XOR(C, T)    ~
705             OR(C, D)     ~
706             XOR(D, A)    ~
707             XOR(C, B)    ~
708             ASSIGN(B, D) ~
709             ASSIGN(D, T);
710     }
711 
712 string SBOX_D6(string A, string B, string C, string D, string T) {
713     return  NOT(B)       ~
714             ASSIGN(T, D) ~
715             XOR(C, B)    ~
716             OR(D, A)     ~
717             XOR(D, C)    ~
718             OR(C, B)     ~
719             AND(C, A)    ~
720             XOR(T, D)    ~
721             XOR(C, T)    ~
722             OR(T, A)     ~
723             XOR(T, B)    ~
724             AND(B, C)    ~
725             XOR(B, D)    ~
726             XOR(T, C)    ~
727             AND(D, T)    ~
728             XOR(T, B)    ~
729             XOR(D, T)    ~
730             NOT(T)       ~
731             XOR(D, A)    ~
732             ASSIGN(A, B) ~
733             ASSIGN(B, T) ~
734             ASSIGN(T, D) ~
735             ASSIGN(D, C) ~
736             ASSIGN(C, T);
737     }
738 
739 string SBOX_D7(string A, string B, string C, string D, string T) {
740     return  XOR(A, C)    ~
741             ASSIGN(T, C) ~
742             AND(C, A)    ~
743             XOR(T, D)    ~
744             NOT(C)       ~
745             XOR(D, B)    ~
746             XOR(C, D)    ~
747             OR(T, A)     ~
748             XOR(A, C)    ~
749             XOR(D, T)    ~
750             XOR(T, B)    ~
751             AND(B, D)    ~
752             XOR(B, A)    ~
753             XOR(A, D)    ~
754             OR(A, C)     ~
755             XOR(D, B)    ~
756             XOR(T, A)    ~
757             ASSIGN(A, B) ~
758             ASSIGN(B, C) ~
759             ASSIGN(C, T);
760 }
761 
762 string SBOX_D8(string A, string B, string C, string D, string T) {
763     return  ASSIGN(T, C) ~
764             XOR(C, A)    ~
765             AND(A, D)    ~
766             OR(T, D)     ~
767             NOT(C)       ~
768             XOR(D, B)    ~
769             OR(B, A)     ~
770             XOR(A, C)    ~
771             AND(C, T)    ~
772             AND(D, T)    ~
773             XOR(B, C)    ~
774             XOR(C, A)    ~
775             OR(A, C)     ~
776             XOR(T, B)    ~
777             XOR(A, D)    ~
778             XOR(D, T)    ~
779             OR(T, A)     ~
780             XOR(D, C)    ~
781             XOR(T, C)    ~
782             ASSIGN(C, B) ~
783             ASSIGN(B, A) ~
784             ASSIGN(A, D) ~
785             ASSIGN(D, T);
786 }