11a59d1b8SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */ 29c201942SThomas Gleixner/*************************************************************************** 39c201942SThomas Gleixner* Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> * 49c201942SThomas Gleixner* * 59c201942SThomas Gleixner***************************************************************************/ 69c201942SThomas Gleixner 79c201942SThomas Gleixner.file "twofish-i586-asm.S" 89c201942SThomas Gleixner.text 99c201942SThomas Gleixner 10d3f5188dSJussi Kivilinna#include <linux/linkage.h> 119c201942SThomas Gleixner#include <asm/asm-offsets.h> 129c201942SThomas Gleixner 133ad2f3fbSDaniel Mack/* return address at 0 */ 149c201942SThomas Gleixner 159c201942SThomas Gleixner#define in_blk 12 /* input byte array address parameter*/ 169c201942SThomas Gleixner#define out_blk 8 /* output byte array address parameter*/ 1791d41f15SJussi Kivilinna#define ctx 4 /* Twofish context structure */ 189c201942SThomas Gleixner 199c201942SThomas Gleixner#define a_offset 0 209c201942SThomas Gleixner#define b_offset 4 219c201942SThomas Gleixner#define c_offset 8 229c201942SThomas Gleixner#define d_offset 12 239c201942SThomas Gleixner 249c201942SThomas Gleixner/* Structure of the crypto context struct*/ 259c201942SThomas Gleixner 269c201942SThomas Gleixner#define s0 0 /* S0 Array 256 Words each */ 279c201942SThomas Gleixner#define s1 1024 /* S1 Array */ 289c201942SThomas Gleixner#define s2 2048 /* S2 Array */ 299c201942SThomas Gleixner#define s3 3072 /* S3 Array */ 309c201942SThomas Gleixner#define w 4096 /* 8 whitening keys (word) */ 319c201942SThomas Gleixner#define k 4128 /* key 1-32 ( word ) */ 329c201942SThomas Gleixner 339c201942SThomas Gleixner/* define a few register aliases to allow macro substitution */ 349c201942SThomas Gleixner 359c201942SThomas Gleixner#define R0D %eax 369c201942SThomas Gleixner#define R0B %al 379c201942SThomas Gleixner#define R0H %ah 389c201942SThomas Gleixner 399c201942SThomas Gleixner#define R1D %ebx 409c201942SThomas Gleixner#define R1B %bl 419c201942SThomas Gleixner#define R1H %bh 429c201942SThomas Gleixner 439c201942SThomas Gleixner#define R2D %ecx 449c201942SThomas Gleixner#define R2B %cl 459c201942SThomas Gleixner#define R2H %ch 469c201942SThomas Gleixner 479c201942SThomas Gleixner#define R3D %edx 489c201942SThomas Gleixner#define R3B %dl 499c201942SThomas Gleixner#define R3H %dh 509c201942SThomas Gleixner 519c201942SThomas Gleixner 529c201942SThomas Gleixner/* performs input whitening */ 539c201942SThomas Gleixner#define input_whitening(src,context,offset)\ 549c201942SThomas Gleixner xor w+offset(context), src; 559c201942SThomas Gleixner 569c201942SThomas Gleixner/* performs input whitening */ 579c201942SThomas Gleixner#define output_whitening(src,context,offset)\ 589c201942SThomas Gleixner xor w+16+offset(context), src; 599c201942SThomas Gleixner 609c201942SThomas Gleixner/* 619c201942SThomas Gleixner * a input register containing a (rotated 16) 629c201942SThomas Gleixner * b input register containing b 639c201942SThomas Gleixner * c input register containing c 649c201942SThomas Gleixner * d input register containing d (already rol $1) 659c201942SThomas Gleixner * operations on a and b are interleaved to increase performance 669c201942SThomas Gleixner */ 679c201942SThomas Gleixner#define encrypt_round(a,b,c,d,round)\ 689c201942SThomas Gleixner push d ## D;\ 699c201942SThomas Gleixner movzx b ## B, %edi;\ 709c201942SThomas Gleixner mov s1(%ebp,%edi,4),d ## D;\ 719c201942SThomas Gleixner movzx a ## B, %edi;\ 729c201942SThomas Gleixner mov s2(%ebp,%edi,4),%esi;\ 739c201942SThomas Gleixner movzx b ## H, %edi;\ 749c201942SThomas Gleixner ror $16, b ## D;\ 759c201942SThomas Gleixner xor s2(%ebp,%edi,4),d ## D;\ 769c201942SThomas Gleixner movzx a ## H, %edi;\ 779c201942SThomas Gleixner ror $16, a ## D;\ 789c201942SThomas Gleixner xor s3(%ebp,%edi,4),%esi;\ 799c201942SThomas Gleixner movzx b ## B, %edi;\ 809c201942SThomas Gleixner xor s3(%ebp,%edi,4),d ## D;\ 819c201942SThomas Gleixner movzx a ## B, %edi;\ 829c201942SThomas Gleixner xor (%ebp,%edi,4), %esi;\ 839c201942SThomas Gleixner movzx b ## H, %edi;\ 849c201942SThomas Gleixner ror $15, b ## D;\ 859c201942SThomas Gleixner xor (%ebp,%edi,4), d ## D;\ 869c201942SThomas Gleixner movzx a ## H, %edi;\ 879c201942SThomas Gleixner xor s1(%ebp,%edi,4),%esi;\ 889c201942SThomas Gleixner pop %edi;\ 899c201942SThomas Gleixner add d ## D, %esi;\ 909c201942SThomas Gleixner add %esi, d ## D;\ 919c201942SThomas Gleixner add k+round(%ebp), %esi;\ 929c201942SThomas Gleixner xor %esi, c ## D;\ 939c201942SThomas Gleixner rol $15, c ## D;\ 949c201942SThomas Gleixner add k+4+round(%ebp),d ## D;\ 959c201942SThomas Gleixner xor %edi, d ## D; 969c201942SThomas Gleixner 979c201942SThomas Gleixner/* 989c201942SThomas Gleixner * a input register containing a (rotated 16) 999c201942SThomas Gleixner * b input register containing b 1009c201942SThomas Gleixner * c input register containing c 1019c201942SThomas Gleixner * d input register containing d (already rol $1) 1029c201942SThomas Gleixner * operations on a and b are interleaved to increase performance 1039c201942SThomas Gleixner * last round has different rotations for the output preparation 1049c201942SThomas Gleixner */ 1059c201942SThomas Gleixner#define encrypt_last_round(a,b,c,d,round)\ 1069c201942SThomas Gleixner push d ## D;\ 1079c201942SThomas Gleixner movzx b ## B, %edi;\ 1089c201942SThomas Gleixner mov s1(%ebp,%edi,4),d ## D;\ 1099c201942SThomas Gleixner movzx a ## B, %edi;\ 1109c201942SThomas Gleixner mov s2(%ebp,%edi,4),%esi;\ 1119c201942SThomas Gleixner movzx b ## H, %edi;\ 1129c201942SThomas Gleixner ror $16, b ## D;\ 1139c201942SThomas Gleixner xor s2(%ebp,%edi,4),d ## D;\ 1149c201942SThomas Gleixner movzx a ## H, %edi;\ 1159c201942SThomas Gleixner ror $16, a ## D;\ 1169c201942SThomas Gleixner xor s3(%ebp,%edi,4),%esi;\ 1179c201942SThomas Gleixner movzx b ## B, %edi;\ 1189c201942SThomas Gleixner xor s3(%ebp,%edi,4),d ## D;\ 1199c201942SThomas Gleixner movzx a ## B, %edi;\ 1209c201942SThomas Gleixner xor (%ebp,%edi,4), %esi;\ 1219c201942SThomas Gleixner movzx b ## H, %edi;\ 1229c201942SThomas Gleixner ror $16, b ## D;\ 1239c201942SThomas Gleixner xor (%ebp,%edi,4), d ## D;\ 1249c201942SThomas Gleixner movzx a ## H, %edi;\ 1259c201942SThomas Gleixner xor s1(%ebp,%edi,4),%esi;\ 1269c201942SThomas Gleixner pop %edi;\ 1279c201942SThomas Gleixner add d ## D, %esi;\ 1289c201942SThomas Gleixner add %esi, d ## D;\ 1299c201942SThomas Gleixner add k+round(%ebp), %esi;\ 1309c201942SThomas Gleixner xor %esi, c ## D;\ 1319c201942SThomas Gleixner ror $1, c ## D;\ 1329c201942SThomas Gleixner add k+4+round(%ebp),d ## D;\ 1339c201942SThomas Gleixner xor %edi, d ## D; 1349c201942SThomas Gleixner 1359c201942SThomas Gleixner/* 1369c201942SThomas Gleixner * a input register containing a 1379c201942SThomas Gleixner * b input register containing b (rotated 16) 1389c201942SThomas Gleixner * c input register containing c 1399c201942SThomas Gleixner * d input register containing d (already rol $1) 1409c201942SThomas Gleixner * operations on a and b are interleaved to increase performance 1419c201942SThomas Gleixner */ 1429c201942SThomas Gleixner#define decrypt_round(a,b,c,d,round)\ 1439c201942SThomas Gleixner push c ## D;\ 1449c201942SThomas Gleixner movzx a ## B, %edi;\ 1459c201942SThomas Gleixner mov (%ebp,%edi,4), c ## D;\ 1469c201942SThomas Gleixner movzx b ## B, %edi;\ 1479c201942SThomas Gleixner mov s3(%ebp,%edi,4),%esi;\ 1489c201942SThomas Gleixner movzx a ## H, %edi;\ 1499c201942SThomas Gleixner ror $16, a ## D;\ 1509c201942SThomas Gleixner xor s1(%ebp,%edi,4),c ## D;\ 1519c201942SThomas Gleixner movzx b ## H, %edi;\ 1529c201942SThomas Gleixner ror $16, b ## D;\ 1539c201942SThomas Gleixner xor (%ebp,%edi,4), %esi;\ 1549c201942SThomas Gleixner movzx a ## B, %edi;\ 1559c201942SThomas Gleixner xor s2(%ebp,%edi,4),c ## D;\ 1569c201942SThomas Gleixner movzx b ## B, %edi;\ 1579c201942SThomas Gleixner xor s1(%ebp,%edi,4),%esi;\ 1589c201942SThomas Gleixner movzx a ## H, %edi;\ 1599c201942SThomas Gleixner ror $15, a ## D;\ 1609c201942SThomas Gleixner xor s3(%ebp,%edi,4),c ## D;\ 1619c201942SThomas Gleixner movzx b ## H, %edi;\ 1629c201942SThomas Gleixner xor s2(%ebp,%edi,4),%esi;\ 1639c201942SThomas Gleixner pop %edi;\ 1649c201942SThomas Gleixner add %esi, c ## D;\ 1659c201942SThomas Gleixner add c ## D, %esi;\ 1669c201942SThomas Gleixner add k+round(%ebp), c ## D;\ 1679c201942SThomas Gleixner xor %edi, c ## D;\ 1689c201942SThomas Gleixner add k+4+round(%ebp),%esi;\ 1699c201942SThomas Gleixner xor %esi, d ## D;\ 1709c201942SThomas Gleixner rol $15, d ## D; 1719c201942SThomas Gleixner 1729c201942SThomas Gleixner/* 1739c201942SThomas Gleixner * a input register containing a 1749c201942SThomas Gleixner * b input register containing b (rotated 16) 1759c201942SThomas Gleixner * c input register containing c 1769c201942SThomas Gleixner * d input register containing d (already rol $1) 1779c201942SThomas Gleixner * operations on a and b are interleaved to increase performance 1789c201942SThomas Gleixner * last round has different rotations for the output preparation 1799c201942SThomas Gleixner */ 1809c201942SThomas Gleixner#define decrypt_last_round(a,b,c,d,round)\ 1819c201942SThomas Gleixner push c ## D;\ 1829c201942SThomas Gleixner movzx a ## B, %edi;\ 1839c201942SThomas Gleixner mov (%ebp,%edi,4), c ## D;\ 1849c201942SThomas Gleixner movzx b ## B, %edi;\ 1859c201942SThomas Gleixner mov s3(%ebp,%edi,4),%esi;\ 1869c201942SThomas Gleixner movzx a ## H, %edi;\ 1879c201942SThomas Gleixner ror $16, a ## D;\ 1889c201942SThomas Gleixner xor s1(%ebp,%edi,4),c ## D;\ 1899c201942SThomas Gleixner movzx b ## H, %edi;\ 1909c201942SThomas Gleixner ror $16, b ## D;\ 1919c201942SThomas Gleixner xor (%ebp,%edi,4), %esi;\ 1929c201942SThomas Gleixner movzx a ## B, %edi;\ 1939c201942SThomas Gleixner xor s2(%ebp,%edi,4),c ## D;\ 1949c201942SThomas Gleixner movzx b ## B, %edi;\ 1959c201942SThomas Gleixner xor s1(%ebp,%edi,4),%esi;\ 1969c201942SThomas Gleixner movzx a ## H, %edi;\ 1979c201942SThomas Gleixner ror $16, a ## D;\ 1989c201942SThomas Gleixner xor s3(%ebp,%edi,4),c ## D;\ 1999c201942SThomas Gleixner movzx b ## H, %edi;\ 2009c201942SThomas Gleixner xor s2(%ebp,%edi,4),%esi;\ 2019c201942SThomas Gleixner pop %edi;\ 2029c201942SThomas Gleixner add %esi, c ## D;\ 2039c201942SThomas Gleixner add c ## D, %esi;\ 2049c201942SThomas Gleixner add k+round(%ebp), c ## D;\ 2059c201942SThomas Gleixner xor %edi, c ## D;\ 2069c201942SThomas Gleixner add k+4+round(%ebp),%esi;\ 2079c201942SThomas Gleixner xor %esi, d ## D;\ 2089c201942SThomas Gleixner ror $1, d ## D; 2099c201942SThomas Gleixner 2106d685e53SJiri SlabySYM_FUNC_START(twofish_enc_blk) 2119c201942SThomas Gleixner push %ebp /* save registers according to calling convention*/ 2129c201942SThomas Gleixner push %ebx 2139c201942SThomas Gleixner push %esi 2149c201942SThomas Gleixner push %edi 2159c201942SThomas Gleixner 21691d41f15SJussi Kivilinna mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base 21791d41f15SJussi Kivilinna * pointer to the ctx address */ 2183ad2f3fbSDaniel Mack mov in_blk+16(%esp),%edi /* input address in edi */ 2199c201942SThomas Gleixner 2209c201942SThomas Gleixner mov (%edi), %eax 2219c201942SThomas Gleixner mov b_offset(%edi), %ebx 2229c201942SThomas Gleixner mov c_offset(%edi), %ecx 2239c201942SThomas Gleixner mov d_offset(%edi), %edx 2249c201942SThomas Gleixner input_whitening(%eax,%ebp,a_offset) 2259c201942SThomas Gleixner ror $16, %eax 2269c201942SThomas Gleixner input_whitening(%ebx,%ebp,b_offset) 2279c201942SThomas Gleixner input_whitening(%ecx,%ebp,c_offset) 2289c201942SThomas Gleixner input_whitening(%edx,%ebp,d_offset) 2299c201942SThomas Gleixner rol $1, %edx 2309c201942SThomas Gleixner 2319c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,0); 2329c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,8); 2339c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,2*8); 2349c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,3*8); 2359c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,4*8); 2369c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,5*8); 2379c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,6*8); 2389c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,7*8); 2399c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,8*8); 2409c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,9*8); 2419c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,10*8); 2429c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,11*8); 2439c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,12*8); 2449c201942SThomas Gleixner encrypt_round(R2,R3,R0,R1,13*8); 2459c201942SThomas Gleixner encrypt_round(R0,R1,R2,R3,14*8); 2469c201942SThomas Gleixner encrypt_last_round(R2,R3,R0,R1,15*8); 2479c201942SThomas Gleixner 2489c201942SThomas Gleixner output_whitening(%eax,%ebp,c_offset) 2499c201942SThomas Gleixner output_whitening(%ebx,%ebp,d_offset) 2509c201942SThomas Gleixner output_whitening(%ecx,%ebp,a_offset) 2519c201942SThomas Gleixner output_whitening(%edx,%ebp,b_offset) 2529c201942SThomas Gleixner mov out_blk+16(%esp),%edi; 2539c201942SThomas Gleixner mov %eax, c_offset(%edi) 2549c201942SThomas Gleixner mov %ebx, d_offset(%edi) 2559c201942SThomas Gleixner mov %ecx, (%edi) 2569c201942SThomas Gleixner mov %edx, b_offset(%edi) 2579c201942SThomas Gleixner 2589c201942SThomas Gleixner pop %edi 2599c201942SThomas Gleixner pop %esi 2609c201942SThomas Gleixner pop %ebx 2619c201942SThomas Gleixner pop %ebp 2629c201942SThomas Gleixner mov $1, %eax 263*14b476e0SPeter Zijlstra RET 2646d685e53SJiri SlabySYM_FUNC_END(twofish_enc_blk) 2659c201942SThomas Gleixner 2666d685e53SJiri SlabySYM_FUNC_START(twofish_dec_blk) 2679c201942SThomas Gleixner push %ebp /* save registers according to calling convention*/ 2689c201942SThomas Gleixner push %ebx 2699c201942SThomas Gleixner push %esi 2709c201942SThomas Gleixner push %edi 2719c201942SThomas Gleixner 2729c201942SThomas Gleixner 27391d41f15SJussi Kivilinna mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base 27491d41f15SJussi Kivilinna * pointer to the ctx address */ 2753ad2f3fbSDaniel Mack mov in_blk+16(%esp),%edi /* input address in edi */ 2769c201942SThomas Gleixner 2779c201942SThomas Gleixner mov (%edi), %eax 2789c201942SThomas Gleixner mov b_offset(%edi), %ebx 2799c201942SThomas Gleixner mov c_offset(%edi), %ecx 2809c201942SThomas Gleixner mov d_offset(%edi), %edx 2819c201942SThomas Gleixner output_whitening(%eax,%ebp,a_offset) 2829c201942SThomas Gleixner output_whitening(%ebx,%ebp,b_offset) 2839c201942SThomas Gleixner ror $16, %ebx 2849c201942SThomas Gleixner output_whitening(%ecx,%ebp,c_offset) 2859c201942SThomas Gleixner output_whitening(%edx,%ebp,d_offset) 2869c201942SThomas Gleixner rol $1, %ecx 2879c201942SThomas Gleixner 2889c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,15*8); 2899c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,14*8); 2909c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,13*8); 2919c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,12*8); 2929c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,11*8); 2939c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,10*8); 2949c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,9*8); 2959c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,8*8); 2969c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,7*8); 2979c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,6*8); 2989c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,5*8); 2999c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,4*8); 3009c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,3*8); 3019c201942SThomas Gleixner decrypt_round(R2,R3,R0,R1,2*8); 3029c201942SThomas Gleixner decrypt_round(R0,R1,R2,R3,1*8); 3039c201942SThomas Gleixner decrypt_last_round(R2,R3,R0,R1,0); 3049c201942SThomas Gleixner 3059c201942SThomas Gleixner input_whitening(%eax,%ebp,c_offset) 3069c201942SThomas Gleixner input_whitening(%ebx,%ebp,d_offset) 3079c201942SThomas Gleixner input_whitening(%ecx,%ebp,a_offset) 3089c201942SThomas Gleixner input_whitening(%edx,%ebp,b_offset) 3099c201942SThomas Gleixner mov out_blk+16(%esp),%edi; 3109c201942SThomas Gleixner mov %eax, c_offset(%edi) 3119c201942SThomas Gleixner mov %ebx, d_offset(%edi) 3129c201942SThomas Gleixner mov %ecx, (%edi) 3139c201942SThomas Gleixner mov %edx, b_offset(%edi) 3149c201942SThomas Gleixner 3159c201942SThomas Gleixner pop %edi 3169c201942SThomas Gleixner pop %esi 3179c201942SThomas Gleixner pop %ebx 3189c201942SThomas Gleixner pop %ebp 3199c201942SThomas Gleixner mov $1, %eax 320*14b476e0SPeter Zijlstra RET 3216d685e53SJiri SlabySYM_FUNC_END(twofish_dec_blk) 322