File Coverage

blib/lib/Crypt/Twofish_PP.pm
Criterion Covered Total %
statement 300 318 94.3
branch 11 16 68.7
condition 5 6 83.3
subroutine 9 14 64.2
pod 5 6 83.3
total 330 360 91.6


line stmt bran cond sub pod time code
1             #! /bin/false
2              
3             # vim: tabstop=4
4             # $Id: Twofish_PP.pm,v 1.8 2003/11/27 15:28:41 guido Exp $
5              
6             # Twofish in pure Perl.
7             # Copyright (C) 2003 Guido Flohr , all rights reserved.
8              
9             # This program is free software; you can redistribute it and/or modify it
10             # under the same terms and conditions as Perl itsels (see the Artistic
11             # license included).
12              
13             package Crypt::Twofish_PP;
14              
15 2     2   2353 use strict;
  2         4  
  2         64  
16 2     2   2076 use integer;
  2         19  
  2         11  
17              
18 2     2   2152 use Locale::TextDomain qw (Crypt-Twofish_PP);
  2         298641  
  2         14  
19              
20 2     2   23417 use vars qw ($VERSION);
  2         6  
  2         1513  
21              
22             $VERSION = '0.17';
23              
24             my @q0 = (
25             169, 103, 179, 232, 4, 253, 163, 118, 154, 146, 128, 120, 228, 221, 209,
26             56, 13, 198, 53, 152, 24, 247, 236, 108, 67, 117, 55, 38, 250, 19, 148,
27             72, 242, 208, 139, 48, 132, 84, 223, 35, 25, 91, 61, 89, 243, 174, 162,
28             130, 99, 1, 131, 46, 217, 81, 155, 124, 166, 235, 165, 190, 22, 12, 227,
29             97, 192, 140, 58, 245, 115, 44, 37, 11, 187, 78, 137, 107, 83, 106, 180,
30             241, 225, 230, 189, 69, 226, 244, 182, 102, 204, 149, 3, 86, 212, 28, 30,
31             215, 251, 195, 142, 181, 233, 207, 191, 186, 234, 119, 57, 175, 51, 201,
32             98, 113, 129, 121, 9, 173, 36, 205, 249, 216, 229, 197, 185, 77, 68, 8,
33             134, 231, 161, 29, 170, 237, 6, 112, 178, 210, 65, 123, 160, 17, 49, 194,
34             39, 144, 32, 246, 96, 255, 150, 92, 177, 171, 158, 156, 82, 27, 95, 147,
35             10, 239, 145, 133, 73, 238, 45, 79, 143, 59, 71, 135, 109, 70, 214, 62,
36             105, 100, 42, 206, 203, 47, 252, 151, 5, 122, 172, 127, 213, 26, 75, 14,
37             167, 90, 40, 20, 63, 41, 136, 60, 76, 2, 184, 218, 176, 23, 85, 31, 138,
38             125, 87, 199, 141, 116, 183, 196, 159, 114, 126, 21, 34, 18, 88, 7, 153,
39             52, 110, 80, 222, 104, 101, 188, 219, 248, 200, 168, 43, 64, 220, 254,
40             50, 164, 202, 16, 33, 240, 211, 93, 15, 0, 111, 157, 54, 66, 74, 94, 193,
41             224
42             );
43             my @q1 = (
44             117, 243, 198, 244, 219, 123, 251, 200, 74, 211, 230, 107, 69, 125, 232,
45             75, 214, 50, 216, 253, 55, 113, 241, 225, 48, 15, 248, 27, 135, 250, 6,
46             63, 94, 186, 174, 91, 138, 0, 188, 157, 109, 193, 177, 14, 128, 93, 210,
47             213, 160, 132, 7, 20, 181, 144, 44, 163, 178, 115, 76, 84, 146, 116, 54,
48             81, 56, 176, 189, 90, 252, 96, 98, 150, 108, 66, 247, 16, 124, 40, 39,
49             140, 19, 149, 156, 199, 36, 70, 59, 112, 202, 227, 133, 203, 17, 208,
50             147, 184, 166, 131, 32, 255, 159, 119, 195, 204, 3, 111, 8, 191, 64, 231,
51             43, 226, 121, 12, 170, 130, 65, 58, 234, 185, 228, 154, 164, 151, 126,
52             218, 122, 23, 102, 148, 161, 29, 61, 240, 222, 179, 11, 114, 167, 28,
53             239, 209, 83, 62, 143, 51, 38, 95, 236, 118, 42, 73, 129, 136, 238, 33,
54             196, 26, 235, 217, 197, 57, 153, 205, 173, 49, 139, 1, 24, 35, 221, 31,
55             78, 45, 249, 72, 79, 242, 101, 142, 120, 92, 88, 25, 141, 229, 152, 87,
56             103, 127, 5, 100, 175, 99, 182, 254, 245, 183, 60, 165, 206, 233, 104,
57             68, 224, 77, 67, 105, 41, 46, 172, 21, 89, 168, 10, 158, 110, 71, 223,
58             52, 53, 106, 207, 220, 34, 201, 192, 155, 137, 212, 237, 171, 18, 162,
59             13, 82, 187, 2, 47, 169, 215, 97, 30, 180, 80, 4, 246, 194, 22, 37, 134,
60             86, 85, 9, 190, 145
61             );
62              
63             my @m0 =
64             (
65             3166450293, 3974898163, 538985414, 3014904308, 3671720923,
66             33721211, 3806473211, 2661219016, 3385453642, 3570665939,
67             404253670, 505323371, 2560101957, 2998024317, 2795950824,
68             640071499, 1010587606, 2475919922, 2189618904, 1381144829,
69             2071712823, 3149608817, 1532729329, 1195869153, 606354480,
70             1364320783, 3132802808, 1246425883, 3216984199, 218984698,
71             2964370182, 1970658879, 3537042782, 2105352378, 1717973422,
72             976921435, 1499012234, 0, 3452801980, 437969053, 2930650221,
73             2139073473, 724289457, 3200170254, 3772817536, 2324303965,
74             993743570, 1684323029, 3638069408, 3890718084, 1600120839,
75             454758676, 741130933, 4244419728, 825304876, 2155898275,
76             1936927410, 202146163, 2037997388, 1802191188, 1263207058,
77             1397975412, 2492763958, 2206408529, 707409464, 3301219504,
78             572704957, 3587569754, 3183330300, 1212708960, 4294954594,
79             1280051094, 1094809452, 3351766594, 3958056183, 471602192,
80             1566401404, 909517352, 1734852647, 3924406156, 1145370899,
81             336915093, 4126522268, 3486456007, 1061104932, 3233866566,
82             1920129851, 1414818928, 690572490, 4042274275, 134807173,
83             3334870987, 4092808977, 2358043856, 2762234259, 3402274488,
84             1751661478, 3099086211, 943204384, 3857002239, 2913818271,
85             185304183, 3368558019, 2577006540, 1482222851, 421108335,
86             235801096, 2509602495, 1886408768, 4160172263, 1852755755,
87             522153698, 3048553849, 151588620, 1633760426, 1465325186,
88             2678000449, 2644344890, 286352618, 623234489, 2947538404,
89             1162152090, 3755969956, 2745392279, 3941258622, 892688602,
90             3991785594, 1128528919, 4177054566, 4227576212, 926405537,
91             4210704413, 3267520573, 3031747824, 842161630, 2627498419,
92             1448535819, 3823360626, 2273796263, 353704732, 4193860335,
93             1667481553, 875866451, 2593817918, 2981184143, 2088554803,
94             2290653990, 1027450463, 2711738348, 3840204662, 2172752938,
95             2442199369, 252705665, 4008618632, 370565614, 3621221153,
96             2543318468, 2779097114, 4278075371, 1835906521, 2021174981,
97             3318050105, 488498585, 1987486925, 1044307117, 3419105073,
98             3065399179, 4025441025, 303177240, 1616954659, 1785376989,
99             1296954911, 3469666638, 3739122733, 1431674361, 2122209864,
100             555856463, 50559730, 2694850149, 1583225230, 1515873912,
101             1701137244, 1650609752, 4261233945, 101119117, 1077970661,
102             4075994776, 859024471, 387420263, 84250239, 3907542533,
103             1330609508, 2307484335, 269522275, 1953771446, 168457726,
104             1549570805, 2610656439, 757936956, 808507045, 774785486,
105             1229556201, 1179021928, 2004309316, 2829637856, 2526413901,
106             673758531, 2846435689, 3654908201, 2256965934, 3520169900,
107             4109650453, 2374833497, 3604382376, 3115957258, 1111625118,
108             4143366510, 791656519, 3722249951, 589510964, 3435946549,
109             4059153514, 3250655951, 2240146396, 2408554018, 1903272393,
110             2425417920, 2863289243, 16904585, 2341200340, 1313770733,
111             2391699371, 2880152082, 1869561506, 3873854477, 3688624722,
112             2459073467, 3082270210, 1768540719, 960092585, 3553823959,
113             2812748641, 2728570142, 3284375988, 1819034704, 117900548,
114             67403766, 656885442, 2896996118, 3503322661, 1347425158,
115             3705468758, 2223250005, 3789639945, 2054825406, 320073617
116             );
117              
118             my @m1 =
119             (
120             2849585465, 1737496343, 3010567324, 3906119334, 67438343,
121             4254618194, 2741338240, 1994384612, 2584233285, 2449623883,
122             2158026976, 2019973722, 3839733679, 3719326314, 3518980963,
123             943073834, 223667942, 3326287904, 895667404, 2562650866,
124             404623890, 4146392043, 3973554593, 1819754817, 1136470056,
125             1966259388, 936672123, 647727240, 4201647373, 335103044,
126             2494692347, 1213890174, 4068082435, 3504639116, 2336732854,
127             809247780, 2225465319, 1413573483, 3741769181, 600137824,
128             424017405, 1537423930, 1030275778, 1494584717, 4079086828,
129             2922473062, 2722000751, 2182502231, 1670713360, 22802415,
130             2202908856, 781289094, 3652545901, 1361019779, 2605951658,
131             2086886749, 2788911208, 3946839806, 2782277680, 3190127226,
132             380087468, 202311945, 3811963120, 1629726631, 3236991120,
133             2360338921, 981507485, 4120009820, 1937837068, 740766001,
134             628543696, 199710294, 3145437842, 1323945678, 2314273025,
135             1805590046, 1403597876, 1791291889, 3029976003, 4053228379,
136             3783477063, 3865778200, 3184009762, 1158584472, 3798867743,
137             4106859443, 3056563316, 1724643576, 3439303065, 2515145748,
138             65886296, 1459084508, 3571551115, 471536917, 514695842,
139             3607942099, 4213957346, 3273509064, 2384027230, 3049401388,
140             3918088521, 3474112961, 3212744085, 3122691453, 3932426513,
141             2005142283, 963495365, 2942994825, 869366908, 3382800753,
142             1657733119, 1899477947, 2180714255, 2034087349, 156361185,
143             2916892222, 606945087, 3450107510, 4187837781, 3639509634,
144             3850780736, 3316545656, 3117229349, 1292146326, 1146451831,
145             134876686, 2249412688, 3878746103, 2714974007, 490797818,
146             2855559521, 3985395278, 112439472, 1886147668, 2989126515,
147             3528604475, 1091280799, 2072707586, 2693322968, 290452467,
148             828885963, 3259377447, 666920807, 2427780348, 539506744,
149             4135519236, 1618495560, 4281263589, 2517060684, 1548445029,
150             2982619947, 2876214926, 2651669058, 2629563893, 1391647707,
151             468929098, 1604730173, 2472125604, 180140473, 4013619705,
152             2448364307, 2248017928, 1224839569, 3999340054, 763158238,
153             1337073953, 2403512753, 1004237426, 1203253039, 2269691839,
154             1831644846, 1189331136, 3596041276, 1048943258, 1764338089,
155             1685933903, 714375553, 3460902446, 3407333062, 801794409,
156             4240686525, 2539430819, 90106088, 2060512749, 2894582225,
157             2140013829, 3585762404, 447260069, 1270294054, 247054014,
158             2808121223, 1526257109, 673330742, 336665371, 1071543669,
159             695851481, 2292903662, 1009986861, 1281325433, 45529015,
160             3096890058, 3663213877, 2963064004, 402408259, 1427801220,
161             536235341, 2317113689, 2100867762, 1470903091, 3340292047,
162             2381579782, 1953059667, 3077872539, 3304429463, 2673257901,
163             1926947811, 2127948522, 357233908, 580816783, 312650667,
164             1481532002, 132669279, 2581929245, 876159779, 1858205430,
165             1346661484, 3730649650, 1752319558, 1697030304, 3163803085,
166             3674462938, 4173773498, 3371867806, 2827146966, 735014510,
167             1079013488, 3706422661, 4269083146, 847942547, 2760761311,
168             3393988905, 269753372, 561240023, 4039947444, 3540636884,
169             1561365130, 266490193, 0, 1872369945, 2648709658, 915379348,
170             1122420679, 1257032137, 1593692882, 3249241983, 3772295336
171             );
172              
173             my @m2 =
174             (
175             3161832498, 3975408673, 549855299, 3019158473, 3671841283,
176             41616011, 3808158251, 2663948026, 3377121772, 3570652169,
177             417732715, 510336671, 2554697742, 2994582072, 2800264914,
178             642459319, 1020673111, 2469565322, 2195227374, 1392333464,
179             2067233748, 3144792887, 1542544279, 1205946243, 607134780,
180             1359958498, 3136862918, 1243302643, 3213344584, 234491248,
181             2953228467, 1967093214, 3529429757, 2109373728, 1722705457,
182             979057315, 1502239004, 0, 3451702675, 446503648, 2926423596,
183             2143387563, 733031367, 3188637369, 3766542496, 2321386000,
184             1003633490, 1691706554, 3634419848, 3884246949, 1594318824,
185             454302481, 750070978, 4237360308, 824979751, 2158198885,
186             1941074730, 208866433, 2035054943, 1800694593, 1267878658,
187             1400132457, 2486604943, 2203157279, 708323894, 3299919004,
188             582820552, 3579500024, 3187457475, 1214269560, 4284678094,
189             1284918279, 1097613687, 3343042534, 3958893348, 470817812,
190             1568431459, 908604962, 1730635712, 3918326191, 1142113529,
191             345314538, 4120704443, 3485978392, 1059340077, 3225862371,
192             1916498651, 1416647788, 701114700, 4041470005, 142936318,
193             3335243287, 4078039887, 2362477796, 2761139289, 3401108118,
194             1755736123, 3095640141, 941635624, 3858752814, 2912922966,
195             192351108, 3368273949, 2580322815, 1476614381, 426711450,
196             235408906, 2512360830, 1883271248, 4159174448, 1848340175,
197             534912878, 3044652349, 151783695, 1638555956, 1468159766,
198             2671877899, 2637864320, 300552548, 632890829, 2951000029,
199             1167738120, 3752124301, 2744623964, 3934186197, 903492952,
200             3984256464, 1125598204, 4167497931, 4220844977, 933312467,
201             4196268608, 3258827368, 3035673804, 853422685, 2629016689,
202             1443583719, 3815957466, 2275903328, 354161947, 4193253690,
203             1674666943, 877868201, 2587794053, 2978984258, 2083749073,
204             2284226715, 1029651878, 2716639703, 3832997087, 2167046548,
205             2437517569, 260116475, 4001951402, 384702049, 3609319283,
206             2546243573, 2769986984, 4276878911, 1842965941, 2026207406,
207             3308897645, 496573925, 1993176740, 1051541212, 3409038183,
208             3062609479, 4009881435, 303567390, 1612931269, 1792895664,
209             1293897206, 3461271273, 3727548028, 1442403741, 2118680154,
210             558834098, 66192250, 2691014694, 1586388505, 1517836902,
211             1700554059, 1649959502, 4246338885, 109905652, 1088766086,
212             4070109886, 861352876, 392632208, 92210574, 3892701278,
213             1331974013, 2309982570, 274927765, 1958114351, 184420981,
214             1559583890, 2612501364, 758918451, 816132310, 785264201,
215             1240025481, 1181238898, 2000975701, 2833295576, 2521667076,
216             675489981, 2842274089, 3643398521, 2251196049, 3517763975,
217             4095079498, 2371456277, 3601389186, 3104487868, 1117667853,
218             4134467265, 793194424, 3722435846, 590619449, 3426077794,
219             4050317764, 3251618066, 2245821931, 2401406878, 1909027233,
220             2428539120, 2862328403, 25756145, 2345962465, 1324174988,
221             2393607791, 2870127522, 1872916286, 3859670612, 3679640562,
222             2461766267, 3070408630, 1764714954, 967391705, 3554136844,
223             2808194851, 2719916717, 3283403673, 1817209924, 117704453,
224             83231871, 667035462, 2887167143, 3492139126, 1350979603,
225             3696680183, 2220196890, 3775521105, 2059303461, 328274927
226             );
227              
228             my @m3 =
229             (
230             3644434905, 2417452944, 1906094961, 3534153938, 84345861,
231             2555575704, 1702929253, 3756291807, 138779144, 38507010,
232             2699067552, 1717205094, 3719292125, 2959793584, 3210990015,
233             908736566, 1424362836, 1126221379, 1657550178, 3203569854,
234             504502302, 619444004, 3617713367, 2000776311, 3173532605,
235             851211570, 3564845012, 2609391259, 1879964272, 4181988345,
236             2986054833, 1518225498, 2047079034, 3834433764, 1203145543,
237             1009004604, 2783413413, 1097552961, 115203846, 3311412165,
238             1174214981, 2738510755, 1757560168, 361584917, 569176865,
239             828812849, 1047503422, 374833686, 2500879253, 1542390107,
240             1303937869, 2441490065, 3043875253, 528699679, 1403689811,
241             1667071075, 996714043, 1073670975, 3593512406, 628801061,
242             2813073063, 252251151, 904979253, 598171939, 4036018416,
243             2951318703, 2157787776, 2455565714, 2165076865, 657533991,
244             1993352566, 3881176039, 2073213819, 3922611945, 4043409905,
245             2669570975, 2838778793, 3304155844, 2579739801, 2539385239,
246             2202526083, 1796793963, 3357720008, 244860174, 1847583342,
247             3384014025, 796177967, 3422054091, 4288269567, 3927217642,
248             3981968365, 4158412535, 3784037601, 454368283, 2913083053,
249             215209740, 736295723, 499696413, 425627161, 3257710018,
250             2303322505, 314691346, 2123743102, 545110560, 1678895716,
251             2215344004, 1841641837, 1787408234, 3514577873, 2708588961,
252             3472843470, 935031095, 4212097531, 1035303229, 1373702481,
253             3695095260, 759112749, 2759249316, 2639657373, 4001552622,
254             2252400006, 2927150510, 3441801677, 76958980, 1433879637,
255             168691722, 324044307, 821552944, 3543638483, 1090133312,
256             878815796, 2353982860, 3014657715, 1817473132, 712225322,
257             1379652178, 194986251, 2332195723, 2295898248, 1341329743,
258             1741369703, 1177010758, 3227985856, 3036450996, 674766888,
259             2131031679, 2018009208, 786825006, 122459655, 1264933963,
260             3341529543, 1871620975, 222469645, 3153435835, 4074459890,
261             4081720307, 2789040038, 1503957849, 3166243516, 989458234,
262             4011037167, 4261971454, 26298625, 1628892769, 2094935420,
263             2988527538, 1118932802, 3681696731, 3090106296, 1220511560,
264             749628716, 3821029091, 1463604823, 2241478277, 698968361,
265             2102355069, 2491493012, 1227804233, 398904087, 3395891146,
266             3284008131, 1554224988, 1592264030, 3505224400, 2278665351,
267             2382725006, 3127170490, 2829392552, 3072740279, 3116240569,
268             1619502944, 4174732024, 573974562, 286987281, 3732226014,
269             2044275065, 2867759274, 858602547, 1601784927, 3065447094,
270             2529867926, 1479924312, 2630135964, 4232255484, 444880154,
271             4132249590, 475630108, 951221560, 2889045932, 416270104,
272             4094070260, 1767076969, 1956362100, 4120364277, 1454219094,
273             3672339162, 3588914901, 1257510218, 2660180638, 2729120418,
274             1315067982, 3898542056, 3843922405, 958608441, 3254152897,
275             1147949124, 1563614813, 1917216882, 648045862, 2479733907,
276             64674563, 3334142150, 4204710138, 2195105922, 3480103887,
277             1349533776, 3951418603, 1963654773, 2324902538, 2380244109,
278             1277807180, 337383444, 1943478643, 3434410188, 164942601,
279             277503248, 3796963298, 0, 2585358234, 3759840736, 2408855183,
280             3871818470, 3972614892, 4258422525, 2877276587, 3634946264
281             );
282              
283             sub __mds_rem;
284             sub __usage;
285             sub __padding_error;
286              
287 2     2   11 use vars qw ($KEYSIZE);
  2         4  
  2         9319  
288              
289             # See method keysize() below for an explanation.
290             $KEYSIZE = 32;
291              
292             sub new
293             {
294 39 50   39 1 8335 __usage (__PACKAGE__ . "->new (key)")
295             unless @_ == 2;
296              
297 39         74 my ($class, $key) = @_;
298              
299 39         211 my @key = unpack "C*", $key;
300 39         86 my $keylength = @key;
301              
302             # FIXME: Turn off UTF-8 on the key!
303 39 50 100     249 __padding_error ($keylength)
      66        
304             unless $keylength == 16 || $keylength == 24 || $keylength == 32;
305              
306             # The key consists of k=len/8 (2, 3 or 4) 64-bit units.
307 39         144 $keylength /= 8;
308              
309 39         109 my $self = {
310             __keylength => $keylength
311             };
312              
313             # We must derive three vectors Me, Mo, and S, each with k 32-bit
314             # words, from the 2k words in the key.
315             #
316             # Me = (key[0], key[2], ..., key[2k-2]) (even words)
317             # Mo = (key[1], key[3], ..., key[2k-1]) (odd words)
318             #
319             # The third vector is derived by multiplying each of the k groups
320             # of 8 bytes from the key by a 4x8 matrix, to get k 32-bit words.
321             #
322             # S = (S[k-1], S[k-2], ..., S[0])
323             #
324             # where S[i] are the 4 bytes from the multiplication, interpreted
325             # as a 32-bit word. As described later, mds_rem is equivalent to
326             # the matrix multiplication, but faster.
327 39         115 my @le_longs = unpack "V*", $key;
328              
329             # The words of the expanded key K are defined using the h function:
330             #
331             # rho = 2^24 + 2^16 + 2^8 + 2^0 (0x01010101)
332             # A[i] = h(2i*rho, Me)
333             # B[i] = ROL(h(2(i+1)*rho, Mo), 8)
334             # K[2i] = (A[i] + B[i]) mod 2^32
335             # K[2i+1] = ROL((A[i] + 2B[i]) mod 2^32, 9)
336             #
337             # rho has the property that, for i = 0..255, the word i*rho
338             # consists of four equal bytes, each with the value i. The function
339             # h is only applied to words of this type, so we only pass it the
340             # value of i.
341 39         105 my @K;
342              
343             # The key-dependent S-boxes used in the g() function are created
344             # below. They are defined by g(X) = h(X, S), where S is the vector
345             # derived from the key. That is, for i=0..3, the S-box S[i] is
346             # formed by mapping from x[i] to y[i] in the h function.
347             #
348             # The relevant lookup tables qN have been precomputed and stored in
349             # tables.h; we also perform full key precomputations incorporating
350             # the MDS matrix multiplications.
351 39         107 my (@S0, @S1, @S2, @S3) = @_;
352 39         47 my ($A, $B, $C);
353 0         0 my ($i, $j);
354 39 100       134 if ($keylength == 2) {
    100          
    50          
355 13         40 my ($s7, $s6, $s5, $s4) = __mds_rem ($le_longs[0], $le_longs[1]);
356 13         31 my ($s3, $s2, $s1, $s0) = __mds_rem ($le_longs[2], $le_longs[3]);
357              
358 13         46 for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
359 260         766 $A = $m0[$q0[$q0[$i] ^ $key[8]] ^ $key[0]] ^
360             $m1[$q0[$q1[$i] ^ $key[9]] ^ $key[1]] ^
361             $m2[$q1[$q0[$i] ^ $key[10]] ^ $key[2]] ^
362             $m3[$q1[$q1[$i] ^ $key[11]] ^ $key[3]];
363 260         707 $B = $m0[$q0[$q0[$j] ^ $key[12]] ^ $key[4]] ^
364             $m1[$q0[$q1[$j] ^ $key[13]] ^ $key[5]] ^
365             $m2[$q1[$q0[$j] ^ $key[14]] ^ $key[6]] ^
366             $m3[$q1[$q1[$j] ^ $key[15]] ^ $key[7]];
367              
368 260         327 $B = ($B << 8) | ($B >> 24 & 0xff);
369 260         369 push @K, $A += $B;
370 260         823 push @K, (($A += $B) << 9 | $A >> 23 & 0x1ff);
371             }
372 13         24 for (0 .. 255) {
373 3328         5180 $S0[$_] = $m0[$q0[$q0[$_] ^ $s4] ^ $s0];
374 3328         5266 $S1[$_] = $m1[$q0[$q1[$_] ^ $s5] ^ $s1];
375 3328         5119 $S2[$_] = $m2[$q1[$q0[$_] ^ $s6] ^ $s2];
376 3328         11462 $S3[$_] = $m3[$q1[$q1[$_] ^ $s7] ^ $s3];
377             }
378             } elsif ($keylength == 3) {
379 13         34 my ($sb, $sa, $s9, $s8) = __mds_rem ($le_longs[0], $le_longs[1]);
380 13         36 my ($s7, $s6, $s5, $s4) = __mds_rem ($le_longs[2], $le_longs[3]);
381 13         31 my ($s3, $s2, $s1, $s0) = __mds_rem ($le_longs[4], $le_longs[5]);
382              
383 13         221 for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
384 260         1207 $A = $m0[$q0[$q0[$q1[$i] ^ $key[16]] ^ $key[8]] ^ $key[0]] ^
385             $m1[$q0[$q1[$q1[$i] ^ $key[17]] ^ $key[9]] ^ $key[1]] ^
386             $m2[$q1[$q0[$q0[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
387             $m3[$q1[$q1[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]];
388 260         1239 $B = $m0[$q0[$q0[$q1[$j] ^ $key[20]] ^ $key[12]] ^ $key[4]] ^
389             $m1[$q0[$q1[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
390             $m2[$q1[$q0[$q0[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
391             $m3[$q1[$q1[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]];
392 260         386 $B = ($B << 8) | ($B >> 24 & 0xff);
393 260         417 push @K, $A += $B;
394 260         904 push @K, (($A += $B) << 9 | $A >> 23 & 0x1ff);
395             }
396 13         27 for (0 .. 255) {
397 3328         6146 $S0[$_] = $m0[$q0[$q0[$q1[$_] ^ $s8] ^ $s4] ^ $s0];
398 3328         20451 $S1[$_] = $m1[$q0[$q1[$q1[$_] ^ $s9] ^ $s5] ^ $s1];
399 3328         4771 $S2[$_] = $m2[$q1[$q0[$q0[$_] ^ $sa] ^ $s6] ^ $s2];
400 3328         6611 $S3[$_] = $m3[$q1[$q1[$q0[$_] ^ $sb] ^ $s7] ^ $s3];
401             }
402             } elsif ($keylength == 4) {
403 13         37 my ($sf, $se, $sd, $sc) = __mds_rem ($le_longs[0], $le_longs[1]);
404 13         31 my ($sb, $sa, $s9, $s8) = __mds_rem ($le_longs[2], $le_longs[3]);
405 13         79 my ($s7, $s6, $s5, $s4) = __mds_rem ($le_longs[4], $le_longs[5]);
406 13         35 my ($s3, $s2, $s1, $s0) = __mds_rem ($le_longs[6], $le_longs[7]);
407              
408 13         46 for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
409 260         1083 $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[24]] ^ $key[16]] ^ $key[8]]
410             ^ $key[0]] ^
411             $m1[$q0[$q1[$q1[$q0[$i] ^ $key[25]] ^ $key[17]] ^ $key[9]]
412             ^ $key[1]] ^
413             $m2[$q1[$q0[$q0[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]]
414             ^ $key[2]] ^
415             $m3[$q1[$q1[$q0[$q1[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]]
416             ^ $key[3]];
417 260         885 $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[28]] ^ $key[20]] ^ $key[12]]
418             ^ $key[4]] ^
419             $m1[$q0[$q1[$q1[$q0[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]]
420             ^ $key[5]] ^
421             $m2[$q1[$q0[$q0[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]]
422             ^ $key[6]] ^
423             $m3[$q1[$q1[$q0[$q1[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]]
424             ^ $key[7]];
425              
426 260         305 $B = ($B << 8) | ($B >> 24 & 0xff);
427 260         346 push @K, $A += $B;
428 260         754 push @K, (($A += $B) << 9 | $A >> 23 & 0x1ff);
429             }
430 13         28 for (0 .. 255) {
431 3328         6827 $S0[$_] = $m0[$q0[$q0[$q1[$q1[$_]^$sc]^$s8]^$s4]^$s0];
432 3328         6139 $S1[$_] = $m1[$q0[$q1[$q1[$q0[$_]^$sd]^$s9]^$s5]^$s1];
433 3328         6471 $S2[$_] = $m2[$q1[$q0[$q0[$q0[$_]^$se]^$sa]^$s6]^$s2];
434 3328         6694 $S3[$_] = $m3[$q1[$q1[$q0[$q1[$_]^$sf]^$sb]^$s7]^$s3];
435             }
436             }
437              
438 39         148 $self->{__K} = \@K;
439 39         148 $self->{__S} = [ \@S0, \@S1, \@S2, \@S3 ];
440              
441 39         428 bless $self, $class;
442             }
443              
444             sub keysize
445             {
446 0     0 1 0 my $self = shift;
447              
448 0 0       0 if (ref $self) {
449 0         0 return $self->{__keylength} * 8;
450             } else {
451             # When called as a class method, return a constant value.
452 0         0 return $KEYSIZE;
453             }
454             }
455              
456             sub blocksize
457             {
458 0     0 1 0 16;
459             }
460              
461             sub new_encrypt {
462 0     0 0 0 my ($self, $plain) = @_;
463            
464 0         0 &{$self->{__encrypt}} ($self, $plain);
  0         0  
465             }
466              
467             sub encrypt
468             {
469 39     39 1 344 my ($self, $cipher) = @_;
470              
471 39         171 my @words = unpack "V4", $cipher;
472 39         90 my $K = $self->{__K};
473              
474 39         314 my $R0 = $K->[0] ^ $words[0];
475 39         66 my $R1 = $K->[1] ^ $words[1];
476 39         57 my $R2 = $K->[2] ^ $words[2];
477 39         53 my $R3 = $K->[3] ^ $words[3];
478              
479 39         46 my ($t0, $t1);
480 39         46 my ($S0, $S1, $S2, $S3) = @{$self->{__S}};
  39         98  
481              
482             # i = 0
483 39         117 $t0 = $S0->[$R0 & 0xff] ^
484             $S1->[($R0 >> 8) & 0xff] ^
485             $S2->[($R0 >> 16) & 0xff] ^
486             $S3->[($R0 >> 24) & 0xff];
487 39         97 $t1 = $S0->[($R1 >> 24) & 0xff] ^
488             $S1->[$R1 & 0xff] ^
489             $S2->[($R1 >> 8) & 0xff] ^
490             $S3->[($R1 >> 16) & 0xff];
491            
492 39         76 $R2 ^= ($t0 + $t1 + $K->[8]);
493 39         69 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
494            
495 39         59 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
496 39         76 $R3 ^= ($t0 + ($t1 << 1) + $K->[9]);
497            
498 39         5379 $t0 = $S0->[$R2 & 0xff] ^
499             $S1->[($R2 >> 8) & 0xff] ^
500             $S2->[($R2 >> 16) & 0xff] ^
501             $S3->[($R2 >> 24) & 0xff];
502 39         102 $t1 = $S0->[($R3 >> 24) & 0xff] ^
503             $S1->[$R3 & 0xff] ^
504             $S2->[($R3 >> 8) & 0xff] ^
505             $S3->[($R3 >> 16) & 0xff];
506            
507 39         57 $R0 ^= ($t0 + $t1 + $K->[10]);
508 39         59 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
509            
510 39         54 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
511 39         74 $R1 ^= ($t0 + ($t1 << 1) + $K->[11]);
512            
513             # i = 1
514 39         260 $t0 = $S0->[$R0 & 0xff] ^
515             $S1->[($R0 >> 8) & 0xff] ^
516             $S2->[($R0 >> 16) & 0xff] ^
517             $S3->[($R0 >> 24) & 0xff];
518 39         88 $t1 = $S0->[($R1 >> 24) & 0xff] ^
519             $S1->[$R1 & 0xff] ^
520             $S2->[($R1 >> 8) & 0xff] ^
521             $S3->[($R1 >> 16) & 0xff];
522            
523 39         61 $R2 ^= ($t0 + $t1 + $K->[12]);
524 39         52 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
525            
526 39         51 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
527 39         94 $R3 ^= ($t0 + ($t1 << 1) + $K->[13]);
528            
529 39         98 $t0 = $S0->[$R2 & 0xff] ^
530             $S1->[($R2 >> 8) & 0xff] ^
531             $S2->[($R2 >> 16) & 0xff] ^
532             $S3->[($R2 >> 24) & 0xff];
533 39         88 $t1 = $S0->[($R3 >> 24) & 0xff] ^
534             $S1->[$R3 & 0xff] ^
535             $S2->[($R3 >> 8) & 0xff] ^
536             $S3->[($R3 >> 16) & 0xff];
537            
538 39         64 $R0 ^= ($t0 + $t1 + $K->[14]);
539 39         56 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
540            
541 39         55 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
542 39         53 $R1 ^= ($t0 + ($t1 << 1) + $K->[15]);
543            
544             # i = 2
545 39         93 $t0 = $S0->[$R0 & 0xff] ^
546             $S1->[($R0 >> 8) & 0xff] ^
547             $S2->[($R0 >> 16) & 0xff] ^
548             $S3->[($R0 >> 24) & 0xff];
549 39         85 $t1 = $S0->[($R1 >> 24) & 0xff] ^
550             $S1->[$R1 & 0xff] ^
551             $S2->[($R1 >> 8) & 0xff] ^
552             $S3->[($R1 >> 16) & 0xff];
553            
554 39         51 $R2 ^= ($t0 + $t1 + $K->[16]);
555 39         50 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
556            
557 39         53 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
558 39         62 $R3 ^= ($t0 + ($t1 << 1) + $K->[17]);
559            
560 39         95 $t0 = $S0->[$R2 & 0xff] ^
561             $S1->[($R2 >> 8) & 0xff] ^
562             $S2->[($R2 >> 16) & 0xff] ^
563             $S3->[($R2 >> 24) & 0xff];
564 39         85 $t1 = $S0->[($R3 >> 24) & 0xff] ^
565             $S1->[$R3 & 0xff] ^
566             $S2->[($R3 >> 8) & 0xff] ^
567             $S3->[($R3 >> 16) & 0xff];
568            
569 39         52 $R0 ^= ($t0 + $t1 + $K->[18]);
570 39         53 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
571            
572 39         53 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
573 39         222 $R1 ^= ($t0 + ($t1 << 1) + $K->[19]);
574            
575             # i = 3
576 39         92 $t0 = $S0->[$R0 & 0xff] ^
577             $S1->[($R0 >> 8) & 0xff] ^
578             $S2->[($R0 >> 16) & 0xff] ^
579             $S3->[($R0 >> 24) & 0xff];
580 39         87 $t1 = $S0->[($R1 >> 24) & 0xff] ^
581             $S1->[$R1 & 0xff] ^
582             $S2->[($R1 >> 8) & 0xff] ^
583             $S3->[($R1 >> 16) & 0xff];
584            
585 39         54 $R2 ^= ($t0 + $t1 + $K->[20]);
586 39         213 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
587            
588 39         71 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
589 39         58 $R3 ^= ($t0 + ($t1 << 1) + $K->[21]);
590            
591 39         102 $t0 = $S0->[$R2 & 0xff] ^
592             $S1->[($R2 >> 8) & 0xff] ^
593             $S2->[($R2 >> 16) & 0xff] ^
594             $S3->[($R2 >> 24) & 0xff];
595 39         149 $t1 = $S0->[($R3 >> 24) & 0xff] ^
596             $S1->[$R3 & 0xff] ^
597             $S2->[($R3 >> 8) & 0xff] ^
598             $S3->[($R3 >> 16) & 0xff];
599            
600 39         63 $R0 ^= ($t0 + $t1 + $K->[22]);
601 39         60 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
602            
603 39         69 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
604 39         55 $R1 ^= ($t0 + ($t1 << 1) + $K->[23]);
605              
606             # i = 4
607 39         97 $t0 = $S0->[$R0 & 0xff] ^
608             $S1->[($R0 >> 8) & 0xff] ^
609             $S2->[($R0 >> 16) & 0xff] ^
610             $S3->[($R0 >> 24) & 0xff];
611 39         198 $t1 = $S0->[($R1 >> 24) & 0xff] ^
612             $S1->[$R1 & 0xff] ^
613             $S2->[($R1 >> 8) & 0xff] ^
614             $S3->[($R1 >> 16) & 0xff];
615            
616 39         57 $R2 ^= ($t0 + $t1 + $K->[24]);
617 39         55 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
618            
619 39         51 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
620 39         57 $R3 ^= ($t0 + ($t1 << 1) + $K->[25]);
621            
622 39         93 $t0 = $S0->[$R2 & 0xff] ^
623             $S1->[($R2 >> 8) & 0xff] ^
624             $S2->[($R2 >> 16) & 0xff] ^
625             $S3->[($R2 >> 24) & 0xff];
626 39         85 $t1 = $S0->[($R3 >> 24) & 0xff] ^
627             $S1->[$R3 & 0xff] ^
628             $S2->[($R3 >> 8) & 0xff] ^
629             $S3->[($R3 >> 16) & 0xff];
630            
631 39         158 $R0 ^= ($t0 + $t1 + $K->[26]);
632 39         52 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
633            
634 39         56 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
635 39         60 $R1 ^= ($t0 + ($t1 << 1) + $K->[27]);
636              
637             # i = 5
638 39         95 $t0 = $S0->[$R0 & 0xff] ^
639             $S1->[($R0 >> 8) & 0xff] ^
640             $S2->[($R0 >> 16) & 0xff] ^
641             $S3->[($R0 >> 24) & 0xff];
642 39         85 $t1 = $S0->[($R1 >> 24) & 0xff] ^
643             $S1->[$R1 & 0xff] ^
644             $S2->[($R1 >> 8) & 0xff] ^
645             $S3->[($R1 >> 16) & 0xff];
646            
647 39         66 $R2 ^= ($t0 + $t1 + $K->[28]);
648 39         46 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
649            
650 39         58 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
651 39         55 $R3 ^= ($t0 + ($t1 << 1) + $K->[29]);
652            
653 39         156 $t0 = $S0->[$R2 & 0xff] ^
654             $S1->[($R2 >> 8) & 0xff] ^
655             $S2->[($R2 >> 16) & 0xff] ^
656             $S3->[($R2 >> 24) & 0xff];
657 39         114 $t1 = $S0->[($R3 >> 24) & 0xff] ^
658             $S1->[$R3 & 0xff] ^
659             $S2->[($R3 >> 8) & 0xff] ^
660             $S3->[($R3 >> 16) & 0xff];
661            
662 39         51 $R0 ^= ($t0 + $t1 + $K->[30]);
663 39         55 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
664            
665 39         53 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
666 39         59 $R1 ^= ($t0 + ($t1 << 1) + $K->[31]);
667            
668             # i = 6
669 39         96 $t0 = $S0->[$R0 & 0xff] ^
670             $S1->[($R0 >> 8) & 0xff] ^
671             $S2->[($R0 >> 16) & 0xff] ^
672             $S3->[($R0 >> 24) & 0xff];
673 39         90 $t1 = $S0->[($R1 >> 24) & 0xff] ^
674             $S1->[$R1 & 0xff] ^
675             $S2->[($R1 >> 8) & 0xff] ^
676             $S3->[($R1 >> 16) & 0xff];
677            
678 39         56 $R2 ^= ($t0 + $t1 + $K->[32]);
679 39         55 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
680            
681 39         52 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
682 39         51 $R3 ^= ($t0 + ($t1 << 1) + $K->[33]);
683            
684 39         89 $t0 = $S0->[$R2 & 0xff] ^
685             $S1->[($R2 >> 8) & 0xff] ^
686             $S2->[($R2 >> 16) & 0xff] ^
687             $S3->[($R2 >> 24) & 0xff];
688 39         87 $t1 = $S0->[($R3 >> 24) & 0xff] ^
689             $S1->[$R3 & 0xff] ^
690             $S2->[($R3 >> 8) & 0xff] ^
691             $S3->[($R3 >> 16) & 0xff];
692            
693 39         56 $R0 ^= ($t0 + $t1 + $K->[34]);
694 39         54 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
695            
696 39         53 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
697 39         56 $R1 ^= ($t0 + ($t1 << 1) + $K->[35]);
698            
699             # i = 7
700 39         85 $t0 = $S0->[$R0 & 0xff] ^
701             $S1->[($R0 >> 8) & 0xff] ^
702             $S2->[($R0 >> 16) & 0xff] ^
703             $S3->[($R0 >> 24) & 0xff];
704 39         89 $t1 = $S0->[($R1 >> 24) & 0xff] ^
705             $S1->[$R1 & 0xff] ^
706             $S2->[($R1 >> 8) & 0xff] ^
707             $S3->[($R1 >> 16) & 0xff];
708            
709 39         129 $R2 ^= ($t0 + $t1 + $K->[36]);
710 39         55 $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
711            
712 39         58 $R3 = (($R3 >> 31) & 1) | ($R3 << 1);
713 39         65 $R3 ^= ($t0 + ($t1 << 1) + $K->[37]);
714            
715 39         105 $t0 = $S0->[$R2 & 0xff] ^
716             $S1->[($R2 >> 8) & 0xff] ^
717             $S2->[($R2 >> 16) & 0xff] ^
718             $S3->[($R2 >> 24) & 0xff];
719 39         80 $t1 = $S0->[($R3 >> 24) & 0xff] ^
720             $S1->[$R3 & 0xff] ^
721             $S2->[($R3 >> 8) & 0xff] ^
722             $S3->[($R3 >> 16) & 0xff];
723            
724 39         54 $R0 ^= ($t0 + $t1 + $K->[38]);
725 39         55 $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
726            
727 39         54 $R1 = (($R1 >> 31) & 1) | ($R1 << 1);
728 39         61 $R1 ^= ($t0 + ($t1 << 1) + $K->[39]);
729            
730 39         403 return pack "V4", ($K->[4] ^ $R2,
731             $K->[5] ^ $R3,
732             $K->[6] ^ $R0,
733             $K->[7] ^ $R1);
734             }
735              
736             sub decrypt
737             {
738 39     39 1 10106 my ($self, $plain) = @_;
739 39         265 my @words = unpack "V4", $plain;
740 39         226 my $K = $self->{__K};
741 39         56 my $S = $self->{__S};
742              
743 39         64 my $R0 = $K->[4] ^ $words[0];
744 39         55 my $R1 = $K->[5] ^ $words[1];
745 39         140 my $R2 = $K->[6] ^ $words[2];
746 39         52 my $R3 = $K->[7] ^ $words[3];
747              
748 39         43 my ($t0, $t1);
749 39         121 my ($S0, $S1, $S2, $S3) = @{$self->{__S}};
  39         91  
750              
751             # i = 7
752 39         121 $t0 = $S0->[$R0 & 0xff] ^
753             $S1->[$R0 >> 8 & 0xff] ^
754             $S2->[$R0 >> 16 & 0xff] ^
755             $S3->[$R0 >> 24 & 0xff];
756 39         93 $t1 = $S0->[$R1 >> 24 & 0xff] ^
757             $S1->[$R1 & 0xff] ^
758             $S2->[$R1 >> 8 & 0xff] ^
759             $S3->[$R1 >> 16 & 0xff];
760            
761 39         56 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
762 39         198 $R2 ^= $t0 + $t1 + $K->[38];
763            
764 39         53 $R3 ^= $t0 + ($t1 << 1) + $K->[39];
765 39         61 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
766            
767 39         106 $t0 = $S0->[$R2 & 0xff] ^
768             $S1->[$R2 >> 8 & 0xff] ^
769             $S2->[$R2 >> 16 & 0xff] ^
770             $S3->[$R2 >> 24 & 0xff];
771 39         91 $t1 = $S0->[$R3 >> 24 & 0xff] ^
772             $S1->[$R3 & 0xff] ^
773             $S2->[$R3 >> 8 & 0xff] ^
774             $S3->[$R3 >> 16 & 0xff];
775            
776 39         50 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
777 39         55 $R0 ^= $t0 + $t1 + $K->[36];
778            
779 39         50 $R1 ^= $t0 + ($t1 << 1) + $K->[37];
780 39         58 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
781            
782             # i = 6
783 39         90 $t0 = $S0->[$R0 & 0xff] ^
784             $S1->[$R0 >> 8 & 0xff] ^
785             $S2->[$R0 >> 16 & 0xff] ^
786             $S3->[$R0 >> 24 & 0xff];
787 39         82 $t1 = $S0->[$R1 >> 24 & 0xff] ^
788             $S1->[$R1 & 0xff] ^
789             $S2->[$R1 >> 8 & 0xff] ^
790             $S3->[$R1 >> 16 & 0xff];
791            
792 39         62 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
793 39         56 $R2 ^= $t0 + $t1 + $K->[34];
794            
795 39         48 $R3 ^= $t0 + ($t1 << 1) + $K->[35];
796 39         56 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
797              
798 39         162 $t0 = $S0->[$R2 & 0xff] ^
799             $S1->[$R2 >> 8 & 0xff] ^
800             $S2->[$R2 >> 16 & 0xff] ^
801             $S3->[$R2 >> 24 & 0xff];
802 39         91 $t1 = $S0->[$R3 >> 24 & 0xff] ^
803             $S1->[$R3 & 0xff] ^
804             $S2->[$R3 >> 8 & 0xff] ^
805             $S3->[$R3 >> 16 & 0xff];
806            
807 39         66 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
808 39         57 $R0 ^= $t0 + $t1 + $K->[32];
809            
810 39         57 $R1 ^= $t0 + ($t1 << 1) + $K->[33];
811 39         55 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
812              
813             # i = 5
814 39         99 $t0 = $S0->[$R0 & 0xff] ^
815             $S1->[$R0 >> 8 & 0xff] ^
816             $S2->[$R0 >> 16 & 0xff] ^
817             $S3->[$R0 >> 24 & 0xff];
818 39         89 $t1 = $S0->[$R1 >> 24 & 0xff] ^
819             $S1->[$R1 & 0xff] ^
820             $S2->[$R1 >> 8 & 0xff] ^
821             $S3->[$R1 >> 16 & 0xff];
822            
823 39         134 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
824 39         50 $R2 ^= $t0 + $t1 + $K->[30];
825            
826 39         49 $R3 ^= $t0 + ($t1 << 1) + $K->[31];
827 39         49 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
828            
829 39         91 $t0 = $S0->[$R2 & 0xff] ^
830             $S1->[$R2 >> 8 & 0xff] ^
831             $S2->[$R2 >> 16 & 0xff] ^
832             $S3->[$R2 >> 24 & 0xff];
833 39         87 $t1 = $S0->[$R3 >> 24 & 0xff] ^
834             $S1->[$R3 & 0xff] ^
835             $S2->[$R3 >> 8 & 0xff] ^
836             $S3->[$R3 >> 16 & 0xff];
837            
838 39         48 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
839 39         57 $R0 ^= $t0 + $t1 + $K->[28];
840            
841 39         54 $R1 ^= $t0 + ($t1 << 1) + $K->[29];
842 39         47 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
843            
844             # i = 4
845 39         167 $t0 = $S0->[$R0 & 0xff] ^
846             $S1->[$R0 >> 8 & 0xff] ^
847             $S2->[$R0 >> 16 & 0xff] ^
848             $S3->[$R0 >> 24 & 0xff];
849 39         152 $t1 = $S0->[$R1 >> 24 & 0xff] ^
850             $S1->[$R1 & 0xff] ^
851             $S2->[$R1 >> 8 & 0xff] ^
852             $S3->[$R1 >> 16 & 0xff];
853            
854 39         58 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
855 39         47 $R2 ^= $t0 + $t1 + $K->[26];
856            
857 39         48 $R3 ^= $t0 + ($t1 << 1) + $K->[27];
858 39         49 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
859            
860 39         85 $t0 = $S0->[$R2 & 0xff] ^
861             $S1->[$R2 >> 8 & 0xff] ^
862             $S2->[$R2 >> 16 & 0xff] ^
863             $S3->[$R2 >> 24 & 0xff];
864 39         99 $t1 = $S0->[$R3 >> 24 & 0xff] ^
865             $S1->[$R3 & 0xff] ^
866             $S2->[$R3 >> 8 & 0xff] ^
867             $S3->[$R3 >> 16 & 0xff];
868            
869 39         56 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
870 39         51 $R0 ^= $t0 + $t1 + $K->[24];
871            
872 39         50 $R1 ^= $t0 + ($t1 << 1) + $K->[25];
873 39         47 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
874            
875             # i = 3
876 39         85 $t0 = $S0->[$R0 & 0xff] ^
877             $S1->[$R0 >> 8 & 0xff] ^
878             $S2->[$R0 >> 16 & 0xff] ^
879             $S3->[$R0 >> 24 & 0xff];
880 39         98 $t1 = $S0->[$R1 >> 24 & 0xff] ^
881             $S1->[$R1 & 0xff] ^
882             $S2->[$R1 >> 8 & 0xff] ^
883             $S3->[$R1 >> 16 & 0xff];
884            
885 39         48 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
886 39         57 $R2 ^= $t0 + $t1 + $K->[22];
887            
888 39         63 $R3 ^= $t0 + ($t1 << 1) + $K->[23];
889 39         62 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
890            
891 39         234 $t0 = $S0->[$R2 & 0xff] ^
892             $S1->[$R2 >> 8 & 0xff] ^
893             $S2->[$R2 >> 16 & 0xff] ^
894             $S3->[$R2 >> 24 & 0xff];
895 39         88 $t1 = $S0->[$R3 >> 24 & 0xff] ^
896             $S1->[$R3 & 0xff] ^
897             $S2->[$R3 >> 8 & 0xff] ^
898             $S3->[$R3 >> 16 & 0xff];
899            
900 39         60 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
901 39         54 $R0 ^= $t0 + $t1 + $K->[20];
902            
903 39         48 $R1 ^= $t0 + ($t1 << 1) + $K->[21];
904 39         486 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
905            
906             # i = 2
907 39         91 $t0 = $S0->[$R0 & 0xff] ^
908             $S1->[$R0 >> 8 & 0xff] ^
909             $S2->[$R0 >> 16 & 0xff] ^
910             $S3->[$R0 >> 24 & 0xff];
911 39         83 $t1 = $S0->[$R1 >> 24 & 0xff] ^
912             $S1->[$R1 & 0xff] ^
913             $S2->[$R1 >> 8 & 0xff] ^
914             $S3->[$R1 >> 16 & 0xff];
915            
916 39         63 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
917 39         50 $R2 ^= $t0 + $t1 + $K->[18];
918            
919 39         122 $R3 ^= $t0 + ($t1 << 1) + $K->[19];
920 39         56 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
921            
922 39         90 $t0 = $S0->[$R2 & 0xff] ^
923             $S1->[$R2 >> 8 & 0xff] ^
924             $S2->[$R2 >> 16 & 0xff] ^
925             $S3->[$R2 >> 24 & 0xff];
926 39         88 $t1 = $S0->[$R3 >> 24 & 0xff] ^
927             $S1->[$R3 & 0xff] ^
928             $S2->[$R3 >> 8 & 0xff] ^
929             $S3->[$R3 >> 16 & 0xff];
930              
931 39         49 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
932 39         55 $R0 ^= $t0 + $t1 + $K->[16];
933            
934 39         48 $R1 ^= $t0 + ($t1 << 1) + $K->[17];
935 39         50 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
936              
937             # i = 1
938 39         228 $t0 = $S0->[$R0 & 0xff] ^
939             $S1->[$R0 >> 8 & 0xff] ^
940             $S2->[$R0 >> 16 & 0xff] ^
941             $S3->[$R0 >> 24 & 0xff];
942 39         82 $t1 = $S0->[$R1 >> 24 & 0xff] ^
943             $S1->[$R1 & 0xff] ^
944             $S2->[$R1 >> 8 & 0xff] ^
945             $S3->[$R1 >> 16 & 0xff];
946            
947 39         59 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
948 39         122 $R2 ^= $t0 + $t1 + $K->[14];
949            
950 39         49 $R3 ^= $t0 + ($t1 << 1) + $K->[15];
951 39         98 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
952            
953 39         95 $t0 = $S0->[$R2 & 0xff] ^
954             $S1->[$R2 >> 8 & 0xff] ^
955             $S2->[$R2 >> 16 & 0xff] ^
956             $S3->[$R2 >> 24 & 0xff];
957 39         188 $t1 = $S0->[$R3 >> 24 & 0xff] ^
958             $S1->[$R3 & 0xff] ^
959             $S2->[$R3 >> 8 & 0xff] ^
960             $S3->[$R3 >> 16 & 0xff];
961            
962 39         52 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
963 39         57 $R0 ^= $t0 + $t1 + $K->[12];
964            
965 39         55 $R1 ^= $t0 + ($t1 << 1) + $K->[13];
966 39         52 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
967            
968             # i = 0
969 39         81 $t0 = $S0->[$R0 & 0xff] ^
970             $S1->[$R0 >> 8 & 0xff] ^
971             $S2->[$R0 >> 16 & 0xff] ^
972             $S3->[$R0 >> 24 & 0xff];
973 39         88 $t1 = $S0->[$R1 >> 24 & 0xff] ^
974             $S1->[$R1 & 0xff] ^
975             $S2->[$R1 >> 8 & 0xff] ^
976             $S3->[$R1 >> 16 & 0xff];
977            
978 39         57 $R2 = $R2 >> 31 & 0x1 | $R2 << 1;
979 39         58 $R2 ^= $t0 + $t1 + $K->[10];
980            
981 39         54 $R3 ^= $t0 + ($t1 << 1) + $K->[11];
982 39         49 $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
983            
984 39         83 $t0 = $S0->[$R2 & 0xff] ^
985             $S1->[$R2 >> 8 & 0xff] ^
986             $S2->[$R2 >> 16 & 0xff] ^
987             $S3->[$R2 >> 24 & 0xff];
988 39         83 $t1 = $S0->[$R3 >> 24 & 0xff] ^
989             $S1->[$R3 & 0xff] ^
990             $S2->[$R3 >> 8 & 0xff] ^
991             $S3->[$R3 >> 16 & 0xff];
992            
993 39         49 $R0 = $R0 >> 31 & 0x1 | $R0 << 1;
994 39         50 $R0 ^= $t0 + $t1 + $K->[8];
995            
996 39         199 $R1 ^= $t0 + ($t1 << 1) + $K->[9];
997 39         53 $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
998            
999 39         331 return pack "V4", ($K->[0] ^ $R2,
1000             $K->[1] ^ $R3,
1001             $K->[2] ^ $R0,
1002             $K->[3] ^ $R1);
1003             }
1004              
1005             sub __usage
1006             {
1007 0     0   0 my $msg = shift;
1008              
1009 0         0 my ($package, $filename, $line, $subr) = caller (1);
1010 0         0 require Carp;
1011 0         0 $Carp::CarpLevel = 2;
1012 0         0 Carp::croak (__"Usage:", " $msg");
1013             }
1014              
1015             sub __padding_error
1016             {
1017 0     0   0 my $keylength = shift;
1018              
1019 0         0 require Carp;
1020 0         0 $Carp::CarpLevel = 2;
1021 0         0 Carp::croak (__x ("wrong key length {keylength}: "
1022             . "key must be 16, 24 or 32 bytes long",
1023             $keylength));
1024             }
1025              
1026             # The (12, 8) Reed Solomon code has the generator polynomial:
1027             #
1028             # g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1
1029             #
1030             # where the coefficients are in the finite field GF(2^8) with a modular
1031             # polynomial a^8+a^6+a^3+a^2+1. To generate the remainder, we have to
1032             # start with a 12th order polynomial with our eight input bytes as the
1033             # coefficients of the 4th to 11th terms:
1034             #
1035             # m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0
1036             #
1037             # We then multiply the generator polynomial by m[7]*x^7 and subtract it
1038             # (XOR in GF(2^8)) from the above to eliminate the x^7 term (the
1039             # arithmetic on the coefficients is done in GF(2^8)). We then multiply
1040             # the generator polynomial by m[6]*x^6 and use this to remove the x^10
1041             # term, and so on until the x^4 term is removed, and we are left with:
1042             #
1043             # r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0]
1044             #
1045             # which give the resulting 4 bytes of the remainder. This is equivalent
1046             # to the matrix multiplication described in the Twofish paper, but is
1047             # much faster.
1048             sub __mds_rem
1049             {
1050 117     117   151 my ($A, $B) = @_;
1051              
1052             # use constant G_MOD => 0x14d;
1053              
1054             # No gain by unrolling this loop.
1055 117         114 my ($t, $u);
1056 117         251 foreach (0 .. 7) {
1057             # Get most significant coefficient.
1058 936         1008 $t = 0xff & ($B >> 24);
1059              
1060             # Shift the others up.
1061 936         1140 $B = ($B << 8) | (0xff & ($A >> 24));
1062 936         1179 $A <<= 8;
1063              
1064 936         838 $u = $t << 1;
1065              
1066             # Subtract the modular polynomial on overflow.
1067 936 100       1694 $u ^= 0x14d if $t & 0x80;
1068              
1069             # Remove t * (a * x^2 + 1).
1070 936         1171 $B ^= $t ^ ($u << 16);
1071              
1072             # Form u = a*t + t/a = t*(a + 1/a).
1073 936         1022 $u ^= 0x7fffffff & ($t >> 1);
1074              
1075             # Add the modular polynomial on underflow.
1076 936 100       1524 $u ^= 0xa6 if $t & 0x01;
1077              
1078             # Remove t * (a + 1/a) * (x^3 + x).
1079 936         1677 $B ^= ($u << 24) | ($u << 8);
1080             }
1081              
1082 117         723 return map 0xff & $_, $B >> 24, $B >> 16, $B >> 8, $B;
1083             }
1084              
1085             1;
1086              
1087             __END__