1<?php
2
3/**
4 * Pure-PHP implementation of Twofish.
5 *
6 * Uses mcrypt, if available, and an internal implementation, otherwise.
7 *
8 * PHP version 5
9 *
10 * Useful resources are as follows:
11 *
12 *  - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
13 *
14 * Here's a short example of how to use this library:
15 * <code>
16 * <?php
17 *    include 'vendor/autoload.php';
18 *
19 *    $twofish = new \phpseclib3\Crypt\Twofish('ctr');
20 *
21 *    $twofish->setKey('12345678901234567890123456789012');
22 *
23 *    $plaintext = str_repeat('a', 1024);
24 *
25 *    echo $twofish->decrypt($twofish->encrypt($plaintext));
26 * ?>
27 * </code>
28 *
29 * @category  Crypt
30 * @package   Twofish
31 * @author    Jim Wigginton <terrafrost@php.net>
32 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
33 * @copyright 2007 Jim Wigginton
34 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
35 * @link      http://phpseclib.sourceforge.net
36 */
37
38namespace phpseclib3\Crypt;
39
40use phpseclib3\Crypt\Common\BlockCipher;
41use phpseclib3\Exception\BadModeException;
42
43/**
44 * Pure-PHP implementation of Twofish.
45 *
46 * @package Twofish
47 * @author  Jim Wigginton <terrafrost@php.net>
48 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
49 * @access  public
50 */
51class Twofish extends BlockCipher
52{
53    /**
54     * The mcrypt specific name of the cipher
55     *
56     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
57     * @var string
58     * @access private
59     */
60    protected $cipher_name_mcrypt = 'twofish';
61
62    /**
63     * Optimizing value while CFB-encrypting
64     *
65     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
66     * @var int
67     * @access private
68     */
69    protected $cfb_init_len = 800;
70
71    /**
72     * Q-Table
73     *
74     * @var array
75     * @access private
76     */
77    private static $q0 = [
78        0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
79        0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
80        0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
81        0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
82        0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
83        0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
84        0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
85        0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
86        0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
87        0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
88        0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
89        0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
90        0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
91        0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
92        0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
93        0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
94        0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
95        0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
96        0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
97        0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
98        0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
99        0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
100        0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
101        0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
102        0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
103        0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
104        0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
105        0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
106        0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
107        0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
108        0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
109        0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
110    ];
111
112    /**
113     * Q-Table
114     *
115     * @var array
116     * @access private
117     */
118    private static $q1 = [
119        0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
120        0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
121        0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
122        0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
123        0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
124        0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
125        0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
126        0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
127        0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
128        0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
129        0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
130        0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
131        0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
132        0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
133        0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
134        0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
135        0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
136        0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
137        0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
138        0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
139        0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
140        0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
141        0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
142        0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
143        0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
144        0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
145        0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
146        0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
147        0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
148        0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
149        0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
150        0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
151    ];
152
153    /**
154     * M-Table
155     *
156     * @var array
157     * @access private
158     */
159    private static $m0 = [
160        0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
161        0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
162        0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
163        0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
164        0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
165        0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
166        0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
167        0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
168        0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
169        0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
170        0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
171        0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
172        0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
173        0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
174        0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
175        0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
176        0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
177        0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
178        0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
179        0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
180        0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
181        0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
182        0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
183        0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
184        0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
185        0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
186        0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
187        0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
188        0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
189        0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
190        0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
191        0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
192    ];
193
194    /**
195     * M-Table
196     *
197     * @var array
198     * @access private
199     */
200    private static $m1 = [
201        0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
202        0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
203        0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
204        0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
205        0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
206        0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
207        0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
208        0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
209        0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
210        0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
211        0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
212        0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
213        0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
214        0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
215        0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
216        0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
217        0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
218        0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
219        0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
220        0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
221        0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
222        0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
223        0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
224        0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
225        0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
226        0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
227        0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
228        0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
229        0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
230        0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
231        0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
232        0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
233    ];
234
235    /**
236     * M-Table
237     *
238     * @var array
239     * @access private
240     */
241    private static $m2 = [
242        0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
243        0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
244        0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
245        0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
246        0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
247        0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
248        0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
249        0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
250        0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
251        0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
252        0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
253        0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
254        0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
255        0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
256        0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
257        0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
258        0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
259        0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
260        0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
261        0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
262        0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
263        0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
264        0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
265        0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
266        0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
267        0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
268        0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
269        0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
270        0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
271        0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
272        0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
273        0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
274    ];
275
276    /**
277     * M-Table
278     *
279     * @var array
280     * @access private
281     */
282    private static $m3 = [
283        0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
284        0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
285        0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
286        0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
287        0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
288        0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
289        0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
290        0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
291        0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
292        0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
293        0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
294        0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
295        0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
296        0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
297        0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
298        0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
299        0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
300        0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
301        0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
302        0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
303        0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
304        0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
305        0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
306        0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
307        0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
308        0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
309        0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
310        0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
311        0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
312        0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
313        0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
314        0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
315    ];
316
317    /**
318     * The Key Schedule Array
319     *
320     * @var array
321     * @access private
322     */
323    private $K = [];
324
325    /**
326     * The Key depended S-Table 0
327     *
328     * @var array
329     * @access private
330     */
331    private $S0 = [];
332
333    /**
334     * The Key depended S-Table 1
335     *
336     * @var array
337     * @access private
338     */
339    private $S1 = [];
340
341    /**
342     * The Key depended S-Table 2
343     *
344     * @var array
345     * @access private
346     */
347    private $S2 = [];
348
349    /**
350     * The Key depended S-Table 3
351     *
352     * @var array
353     * @access private
354     */
355    private $S3 = [];
356
357    /**
358     * Holds the last used key
359     *
360     * @var array
361     * @access private
362     */
363    private $kl;
364
365    /**
366     * The Key Length (in bytes)
367     *
368     * @see Crypt_Twofish::setKeyLength()
369     * @var int
370     * @access private
371     */
372    protected $key_length = 16;
373
374    /**
375     * Default Constructor.
376     *
377     * @param string $mode
378     * @access public
379     * @throws BadModeException if an invalid / unsupported mode is provided
380     */
381    public function __construct($mode)
382    {
383        parent::__construct($mode);
384
385        if ($this->mode == self::MODE_STREAM) {
386            throw new BadModeException('Block ciphers cannot be ran in stream mode');
387        }
388    }
389
390    /**
391     * Sets the key length.
392     *
393     * Valid key lengths are 128, 192 or 256 bits
394     *
395     * @access public
396     * @param int $length
397     */
398    public function setKeyLength($length)
399    {
400        switch ($length) {
401            case 128:
402            case 192:
403            case 256:
404                break;
405            default:
406                throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
407        }
408
409        parent::setKeyLength($length);
410    }
411
412    /**
413     * Sets the key.
414     *
415     * Rijndael supports five different key lengths
416     *
417     * @see setKeyLength()
418     * @access public
419     * @param string $key
420     * @throws \LengthException if the key length isn't supported
421     */
422    public function setKey($key)
423    {
424        switch (strlen($key)) {
425            case 16:
426            case 24:
427            case 32:
428                break;
429            default:
430                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
431        }
432
433        parent::setKey($key);
434    }
435
436    /**
437     * Setup the key (expansion)
438     *
439     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
440     * @access private
441     */
442    protected function setupKey()
443    {
444        if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
445            // already expanded
446            return;
447        }
448        $this->kl = ['key' => $this->key];
449
450        /* Key expanding and generating the key-depended s-boxes */
451        $le_longs = unpack('V*', $this->key);
452        $key = unpack('C*', $this->key);
453        $m0 = self::$m0;
454        $m1 = self::$m1;
455        $m2 = self::$m2;
456        $m3 = self::$m3;
457        $q0 = self::$q0;
458        $q1 = self::$q1;
459
460        $K = $S0 = $S1 = $S2 = $S3 = [];
461
462        switch (strlen($this->key)) {
463            case 16:
464                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[1], $le_longs[2]);
465                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[3], $le_longs[4]);
466                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
467                    $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
468                         $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
469                         $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
470                         $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
471                    $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
472                         $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
473                         $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
474                         $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
475                    $B = ($B << 8) | ($B >> 24 & 0xff);
476                    $A = self::safe_intval($A + $B);
477                    $K[] = $A;
478                    $A = self::safe_intval($A + $B);
479                    $K[] = ($A << 9 | $A >> 23 & 0x1ff);
480                }
481                for ($i = 0; $i < 256; ++$i) {
482                    $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
483                    $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
484                    $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
485                    $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
486                }
487                break;
488            case 24:
489                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[1], $le_longs[2]);
490                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[3], $le_longs[4]);
491                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[5], $le_longs[6]);
492                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
493                    $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
494                         $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
495                         $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
496                         $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
497                    $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
498                         $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
499                         $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
500                         $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
501                    $B = ($B << 8) | ($B >> 24 & 0xff);
502                    $A = self::safe_intval($A + $B);
503                    $K[] = $A;
504                    $A = self::safe_intval($A + $B);
505                    $K[] = ($A << 9 | $A >> 23 & 0x1ff);
506                }
507                for ($i = 0; $i < 256; ++$i) {
508                    $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
509                    $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
510                    $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
511                    $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
512                }
513                break;
514            default: // 32
515                list($sf, $se, $sd, $sc) = $this->mdsrem($le_longs[1], $le_longs[2]);
516                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[3], $le_longs[4]);
517                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[5], $le_longs[6]);
518                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[7], $le_longs[8]);
519                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
520                    $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
521                         $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
522                         $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
523                         $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
524                    $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
525                         $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
526                         $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
527                         $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
528                    $B = ($B << 8) | ($B >> 24 & 0xff);
529                    $A = self::safe_intval($A + $B);
530                    $K[] = $A;
531                    $A = self::safe_intval($A + $B);
532                    $K[] = ($A << 9 | $A >> 23 & 0x1ff);
533                }
534                for ($i = 0; $i < 256; ++$i) {
535                    $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
536                    $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
537                    $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
538                    $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
539                }
540        }
541
542        $this->K  = $K;
543        $this->S0 = $S0;
544        $this->S1 = $S1;
545        $this->S2 = $S2;
546        $this->S3 = $S3;
547    }
548
549    /**
550     * _mdsrem function using by the twofish cipher algorithm
551     *
552     * @access private
553     * @param string $A
554     * @param string $B
555     * @return array
556     */
557    private function mdsrem($A, $B)
558    {
559        // No gain by unrolling this loop.
560        for ($i = 0; $i < 8; ++$i) {
561            // Get most significant coefficient.
562            $t = 0xff & ($B >> 24);
563
564            // Shift the others up.
565            $B = ($B << 8) | (0xff & ($A >> 24));
566            $A <<= 8;
567
568            $u = $t << 1;
569
570            // Subtract the modular polynomial on overflow.
571            if ($t & 0x80) {
572                $u ^= 0x14d;
573            }
574
575            // Remove t * (a * x^2 + 1).
576            $B ^= $t ^ ($u << 16);
577
578            // Form u = a*t + t/a = t*(a + 1/a).
579            $u ^= 0x7fffffff & ($t >> 1);
580
581            // Add the modular polynomial on underflow.
582            if ($t & 0x01) {
583                $u ^= 0xa6 ;
584            }
585
586            // Remove t * (a + 1/a) * (x^3 + x).
587            $B ^= ($u << 24) | ($u << 8);
588        }
589
590        return [
591            0xff & $B >> 24,
592            0xff & $B >> 16,
593            0xff & $B >>  8,
594            0xff & $B];
595    }
596
597    /**
598     * Encrypts a block
599     *
600     * @access private
601     * @param string $in
602     * @return string
603     */
604    protected function encryptBlock($in)
605    {
606        $S0 = $this->S0;
607        $S1 = $this->S1;
608        $S2 = $this->S2;
609        $S3 = $this->S3;
610        $K  = $this->K;
611
612        $in = unpack("V4", $in);
613        $R0 = $K[0] ^ $in[1];
614        $R1 = $K[1] ^ $in[2];
615        $R2 = $K[2] ^ $in[3];
616        $R3 = $K[3] ^ $in[4];
617
618        $ki = 7;
619        while ($ki < 39) {
620            $t0 = $S0[ $R0        & 0xff] ^
621                  $S1[($R0 >>  8) & 0xff] ^
622                  $S2[($R0 >> 16) & 0xff] ^
623                  $S3[($R0 >> 24) & 0xff];
624            $t1 = $S0[($R1 >> 24) & 0xff] ^
625                  $S1[ $R1        & 0xff] ^
626                  $S2[($R1 >>  8) & 0xff] ^
627                  $S3[($R1 >> 16) & 0xff];
628            $R2 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
629            $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
630            $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
631
632            $t0 = $S0[ $R2        & 0xff] ^
633                  $S1[($R2 >>  8) & 0xff] ^
634                  $S2[($R2 >> 16) & 0xff] ^
635                  $S3[($R2 >> 24) & 0xff];
636            $t1 = $S0[($R3 >> 24) & 0xff] ^
637                  $S1[ $R3        & 0xff] ^
638                  $S2[($R3 >>  8) & 0xff] ^
639                  $S3[($R3 >> 16) & 0xff];
640            $R0 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
641            $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
642            $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
643        }
644
645        // @codingStandardsIgnoreStart
646        return pack("V4", $K[4] ^ $R2,
647                          $K[5] ^ $R3,
648                          $K[6] ^ $R0,
649                          $K[7] ^ $R1);
650        // @codingStandardsIgnoreEnd
651    }
652
653    /**
654     * Decrypts a block
655     *
656     * @access private
657     * @param string $in
658     * @return string
659     */
660    protected function decryptBlock($in)
661    {
662        $S0 = $this->S0;
663        $S1 = $this->S1;
664        $S2 = $this->S2;
665        $S3 = $this->S3;
666        $K  = $this->K;
667
668        $in = unpack("V4", $in);
669        $R0 = $K[4] ^ $in[1];
670        $R1 = $K[5] ^ $in[2];
671        $R2 = $K[6] ^ $in[3];
672        $R3 = $K[7] ^ $in[4];
673
674        $ki = 40;
675        while ($ki > 8) {
676            $t0 = $S0[$R0       & 0xff] ^
677                  $S1[$R0 >>  8 & 0xff] ^
678                  $S2[$R0 >> 16 & 0xff] ^
679                  $S3[$R0 >> 24 & 0xff];
680            $t1 = $S0[$R1 >> 24 & 0xff] ^
681                  $S1[$R1       & 0xff] ^
682                  $S2[$R1 >>  8 & 0xff] ^
683                  $S3[$R1 >> 16 & 0xff];
684            $R3 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
685            $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
686            $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
687
688            $t0 = $S0[$R2       & 0xff] ^
689                  $S1[$R2 >>  8 & 0xff] ^
690                  $S2[$R2 >> 16 & 0xff] ^
691                  $S3[$R2 >> 24 & 0xff];
692            $t1 = $S0[$R3 >> 24 & 0xff] ^
693                  $S1[$R3       & 0xff] ^
694                  $S2[$R3 >>  8 & 0xff] ^
695                  $S3[$R3 >> 16 & 0xff];
696            $R1 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
697            $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
698            $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
699        }
700
701        // @codingStandardsIgnoreStart
702        return pack("V4", $K[0] ^ $R2,
703                          $K[1] ^ $R3,
704                          $K[2] ^ $R0,
705                          $K[3] ^ $R1);
706        // @codingStandardsIgnoreEnd
707    }
708
709    /**
710     * Setup the performance-optimized function for de/encrypt()
711     *
712     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
713     * @access private
714     */
715    protected function setupInlineCrypt()
716    {
717        $K = $this->K;
718        $init_crypt = '
719            static $S0, $S1, $S2, $S3;
720            if (!$S0) {
721                for ($i = 0; $i < 256; ++$i) {
722                    $S0[] = (int)$this->S0[$i];
723                    $S1[] = (int)$this->S1[$i];
724                    $S2[] = (int)$this->S2[$i];
725                    $S3[] = (int)$this->S3[$i];
726                }
727            }
728        ';
729
730        $safeint = self::safe_intval_inline();
731
732        // Generating encrypt code:
733        $encrypt_block = '
734            $in = unpack("V4", $in);
735            $R0 = ' . $K[0] . ' ^ $in[1];
736            $R1 = ' . $K[1] . ' ^ $in[2];
737            $R2 = ' . $K[2] . ' ^ $in[3];
738            $R3 = ' . $K[3] . ' ^ $in[4];
739        ';
740        for ($ki = 7, $i = 0; $i < 8; ++$i) {
741            $encrypt_block .= '
742                $t0 = $S0[ $R0        & 0xff] ^
743                      $S1[($R0 >>  8) & 0xff] ^
744                      $S2[($R0 >> 16) & 0xff] ^
745                      $S3[($R0 >> 24) & 0xff];
746                $t1 = $S0[($R1 >> 24) & 0xff] ^
747                      $S1[ $R1        & 0xff] ^
748                      $S2[($R1 >>  8) & 0xff] ^
749                      $S3[($R1 >> 16) & 0xff];
750                    $R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
751                $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
752                $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
753
754                $t0 = $S0[ $R2        & 0xff] ^
755                      $S1[($R2 >>  8) & 0xff] ^
756                      $S2[($R2 >> 16) & 0xff] ^
757                      $S3[($R2 >> 24) & 0xff];
758                $t1 = $S0[($R3 >> 24) & 0xff] ^
759                      $S1[ $R3        & 0xff] ^
760                      $S2[($R3 >>  8) & 0xff] ^
761                      $S3[($R3 >> 16) & 0xff];
762                $R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
763                $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
764                $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
765            ';
766        }
767        $encrypt_block .= '
768            $in = pack("V4", ' . $K[4] . ' ^ $R2,
769                             ' . $K[5] . ' ^ $R3,
770                             ' . $K[6] . ' ^ $R0,
771                             ' . $K[7] . ' ^ $R1);
772        ';
773
774        // Generating decrypt code:
775        $decrypt_block = '
776            $in = unpack("V4", $in);
777            $R0 = ' . $K[4] . ' ^ $in[1];
778            $R1 = ' . $K[5] . ' ^ $in[2];
779            $R2 = ' . $K[6] . ' ^ $in[3];
780            $R3 = ' . $K[7] . ' ^ $in[4];
781        ';
782        for ($ki = 40, $i = 0; $i < 8; ++$i) {
783            $decrypt_block .= '
784                $t0 = $S0[$R0       & 0xff] ^
785                      $S1[$R0 >>  8 & 0xff] ^
786                      $S2[$R0 >> 16 & 0xff] ^
787                      $S3[$R0 >> 24 & 0xff];
788                $t1 = $S0[$R1 >> 24 & 0xff] ^
789                      $S1[$R1       & 0xff] ^
790                      $S2[$R1 >>  8 & 0xff] ^
791                      $S3[$R1 >> 16 & 0xff];
792                $R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
793                $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
794                $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';
795
796                $t0 = $S0[$R2       & 0xff] ^
797                      $S1[$R2 >>  8 & 0xff] ^
798                      $S2[$R2 >> 16 & 0xff] ^
799                      $S3[$R2 >> 24 & 0xff];
800                $t1 = $S0[$R3 >> 24 & 0xff] ^
801                      $S1[$R3       & 0xff] ^
802                      $S2[$R3 >>  8 & 0xff] ^
803                      $S3[$R3 >> 16 & 0xff];
804                $R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
805                $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
806                $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';
807            ';
808        }
809        $decrypt_block .= '
810            $in = pack("V4", ' . $K[0] . ' ^ $R2,
811                             ' . $K[1] . ' ^ $R3,
812                             ' . $K[2] . ' ^ $R0,
813                             ' . $K[3] . ' ^ $R1);
814        ';
815
816        $this->inline_crypt = $this->createInlineCryptFunction(
817            [
818               'init_crypt'    => $init_crypt,
819               'init_encrypt'  => '',
820               'init_decrypt'  => '',
821               'encrypt_block' => $encrypt_block,
822               'decrypt_block' => $decrypt_block
823            ]
824        );
825    }
826}
827