Merge branch 'cpus4096-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6] / crypto / cast6.c
1 /* Kernel cryptographic api.
2  * cast6.c - Cast6 cipher algorithm [rfc2612].
3  *
4  * CAST-256 (*cast6*) is a DES like Substitution-Permutation Network (SPN)
5  * cryptosystem built upon the CAST-128 (*cast5*) [rfc2144] encryption
6  * algorithm.
7  *
8  * Copyright (C) 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  */
19
20
21 #include <asm/byteorder.h>
22 #include <linux/init.h>
23 #include <linux/crypto.h>
24 #include <linux/module.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/types.h>
28
29 #define CAST6_BLOCK_SIZE 16
30 #define CAST6_MIN_KEY_SIZE 16
31 #define CAST6_MAX_KEY_SIZE 32
32
33 struct cast6_ctx {
34         u32 Km[12][4];
35         u8 Kr[12][4];
36 };
37
38 #define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol32(I,(r))),   \
39     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
40 #define F2(D,r,m)  (  (I = ((m) ^ (D))), (I=rol32(I,(r))),   \
41     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
42 #define F3(D,r,m)  (  (I = ((m) - (D))), (I=rol32(I,(r))),   \
43     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
44
45 static const u32 s1[256] = {
46         0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
47         0x9c004dd3, 0x6003e540, 0xcf9fc949,
48         0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
49         0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
50         0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
51         0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
52         0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
53         0xaa54166b, 0x22568e3a, 0xa2d341d0,
54         0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
55         0x4a97c1d8, 0x527644b7, 0xb5f437a7,
56         0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
57         0x90ecf52e, 0x22b0c054, 0xbc8e5935,
58         0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
59         0xe93b159f, 0xb48ee411, 0x4bff345d,
60         0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
61         0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
62         0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
63         0xc59c5319, 0xb949e354, 0xb04669fe,
64         0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
65         0x6a390493, 0xe63d37e0, 0x2a54f6b3,
66         0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
67         0xf61b1891, 0xbb72275e, 0xaa508167,
68         0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
69         0xa2d1936b, 0x2ad286af, 0xaa56d291,
70         0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
71         0x73e2bb14, 0xa0bebc3c, 0x54623779,
72         0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
73         0x89fe78e6, 0x3fab0950, 0x325ff6c2,
74         0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
75         0x380782d5, 0xc7fa5cf6, 0x8ac31511,
76         0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
77         0x051ef495, 0xaa573b04, 0x4a805d8d,
78         0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
79         0x50afd341, 0xa7c13275, 0x915a0bf5,
80         0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
81         0xab85c5f3, 0x1b55db94, 0xaad4e324,
82         0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
83         0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
84         0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
85         0x22513f1e, 0xaa51a79b, 0x2ad344cc,
86         0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
87         0x032268d4, 0xc9600acc, 0xce387e6d,
88         0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
89         0x4736f464, 0x5ad328d8, 0xb347cc96,
90         0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
91         0xbfc5fe4a, 0xa70aec10, 0xac39570a,
92         0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
93         0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
94         0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
95         0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
96         0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
97         0x51c85f4d, 0x56907596, 0xa5bb15e6,
98         0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
99         0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
100         0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
101         0x700b45e1, 0xd5ea50f1, 0x85a92872,
102         0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
103         0x0cd0ede7, 0x26470db8, 0xf881814c,
104         0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
105         0xab838653, 0x6e2f1e23, 0x83719c9e,
106         0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
107         0xe1e696ff, 0xb141ab08, 0x7cca89b9,
108         0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
109         0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
110 };
111
112 static const u32 s2[256] = {
113         0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
114         0xeec5207a, 0x55889c94, 0x72fc0651,
115         0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
116         0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
117         0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
118         0xef944459, 0xba83ccb3, 0xe0c3cdfb,
119         0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
120         0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
121         0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
122         0x77e83f4e, 0x79929269, 0x24fa9f7b,
123         0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
124         0x0d554b63, 0x5d681121, 0xc866c359,
125         0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
126         0x39f7627f, 0x361e3084, 0xe4eb573b,
127         0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
128         0x99847ab4, 0xa0e3df79, 0xba6cf38c,
129         0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
130         0x8f458c74, 0xd9e0a227, 0x4ec73a34,
131         0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
132         0x1d804366, 0x721d9bfd, 0xa58684bb,
133         0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
134         0x27e19ba5, 0xd5a6c252, 0xe49754bd,
135         0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
136         0xe0b56714, 0x21f043b7, 0xe5d05860,
137         0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
138         0x68561be6, 0x83ca6b94, 0x2d6ed23b,
139         0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
140         0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
141         0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
142         0xb96726d1, 0x8049a7e8, 0x22b7da7b,
143         0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
144         0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
145         0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
146         0xe3214517, 0xb4542835, 0x9f63293c,
147         0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
148         0x30a22c95, 0x31a70850, 0x60930f13,
149         0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
150         0xa02b1741, 0x7cbad9a2, 0x2180036f,
151         0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
152         0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
153         0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
154         0x846a3bae, 0x8ff77888, 0xee5d60f6,
155         0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
156         0x157fd7fa, 0xef8579cc, 0xd152de58,
157         0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
158         0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
159         0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
160         0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
161         0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
162         0x301e16e6, 0x273be979, 0xb0ffeaa6,
163         0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
164         0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
165         0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
166         0x1a513742, 0xef6828bc, 0x520365d6,
167         0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
168         0x5eea29cb, 0x145892f5, 0x91584f7f,
169         0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
170         0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
171         0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
172         0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
173         0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
174         0xa345415e, 0x5c038323, 0x3e5d3bb9,
175         0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
176         0x73bfbe70, 0x83877605, 0x4523ecf1
177 };
178
179 static const u32 s3[256] = {
180         0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
181         0x369fe44b, 0x8c1fc644, 0xaececa90,
182         0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
183         0xf0ad0548, 0xe13c8d83, 0x927010d5,
184         0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
185         0xfade82e0, 0xa067268b, 0x8272792e,
186         0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
187         0x825b1bfd, 0x9255c5ed, 0x1257a240,
188         0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
189         0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
190         0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
191         0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
192         0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
193         0x4a012d6e, 0xc5884a28, 0xccc36f71,
194         0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
195         0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
196         0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
197         0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
198         0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
199         0x1eac5790, 0x796fb449, 0x8252dc15,
200         0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
201         0xe83ec305, 0x4f91751a, 0x925669c2,
202         0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
203         0x927985b2, 0x8276dbcb, 0x02778176,
204         0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
205         0x340ce5c8, 0x96bbb682, 0x93b4b148,
206         0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
207         0x8437aa88, 0x7d29dc96, 0x2756d3dc,
208         0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
209         0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
210         0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
211         0xbda8229c, 0x127dadaa, 0x438a074e,
212         0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
213         0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
214         0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
215         0x76a2e214, 0xb9a40368, 0x925d958f,
216         0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
217         0x193cbcfa, 0x27627545, 0x825cf47a,
218         0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
219         0x8272a972, 0x9270c4a8, 0x127de50b,
220         0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
221         0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
222         0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
223         0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
224         0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
225         0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
226         0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
227         0x7c34671c, 0x02717ef6, 0x4feb5536,
228         0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
229         0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
230         0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
231         0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
232         0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
233         0x856302e0, 0x72dbd92b, 0xee971b69,
234         0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
235         0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
236         0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
237         0x0ff0443d, 0x606e6dc6, 0x60543a49,
238         0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
239         0x68458425, 0x99833be5, 0x600d457d,
240         0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
241         0x9c305a00, 0x52bce688, 0x1b03588a,
242         0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
243         0xa133c501, 0xe9d3531c, 0xee353783
244 };
245
246 static const u32 s4[256] = {
247         0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
248         0x64ad8c57, 0x85510443, 0xfa020ed1,
249         0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
250         0x6497b7b1, 0xf3641f63, 0x241e4adf,
251         0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
252         0xc0a5374f, 0x1d2d00d9, 0x24147b15,
253         0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
254         0x0c13fefe, 0x081b08ca, 0x05170121,
255         0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
256         0x06df4261, 0xbb9e9b8a, 0x7293ea25,
257         0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
258         0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
259         0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
260         0x11b638e1, 0x72500e03, 0xf80eb2bb,
261         0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
262         0x6920318f, 0x081dbb99, 0xffc304a5,
263         0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
264         0x9f926f91, 0x9f46222f, 0x3991467d,
265         0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
266         0x3fb6180c, 0x18f8931e, 0x281658e6,
267         0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
268         0x79098b02, 0xe4eabb81, 0x28123b23,
269         0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
270         0x0014377b, 0x041e8ac8, 0x09114003,
271         0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
272         0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
273         0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
274         0x56c8c391, 0x6b65811c, 0x5e146119,
275         0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
276         0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
277         0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
278         0xeca1d7c7, 0x041afa32, 0x1d16625a,
279         0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
280         0xc70b8b46, 0xd9e66a48, 0x56e55a79,
281         0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
282         0xedda04eb, 0x17a9be04, 0x2c18f4df,
283         0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
284         0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
285         0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
286         0x0418f2c8, 0x001a96a6, 0x0d1526ab,
287         0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
288         0x311170a7, 0x3e9b640c, 0xcc3e10d7,
289         0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
290         0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
291         0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
292         0xb4be31cd, 0xd8782806, 0x12a3a4e2,
293         0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
294         0x9711aac5, 0x001d7b95, 0x82e5e7d2,
295         0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
296         0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
297         0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
298         0x0ce454a9, 0xd60acd86, 0x015f1919,
299         0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
300         0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
301         0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
302         0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
303         0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
304         0x296b299e, 0x492fc295, 0x9266beab,
305         0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
306         0xf65324e6, 0x6afce36c, 0x0316cc04,
307         0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
308         0x932bcdf6, 0xb657c34d, 0x4edfd282,
309         0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
310         0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
311 };
312
313 static const u32 Tm[24][8] = {
314         { 0x5a827999, 0xc95c653a, 0x383650db, 0xa7103c7c, 0x15ea281d,
315                 0x84c413be, 0xf39dff5f, 0x6277eb00 } , 
316         { 0xd151d6a1, 0x402bc242, 0xaf05ade3, 0x1ddf9984, 0x8cb98525,
317                 0xfb9370c6, 0x6a6d5c67, 0xd9474808 } ,
318         { 0x482133a9, 0xb6fb1f4a, 0x25d50aeb, 0x94aef68c, 0x0388e22d,
319                 0x7262cdce, 0xe13cb96f, 0x5016a510 } ,
320         { 0xbef090b1, 0x2dca7c52, 0x9ca467f3, 0x0b7e5394, 0x7a583f35,
321                 0xe9322ad6, 0x580c1677, 0xc6e60218 } ,
322         { 0x35bfedb9, 0xa499d95a, 0x1373c4fb, 0x824db09c, 0xf1279c3d,
323                 0x600187de, 0xcedb737f, 0x3db55f20 } ,
324         { 0xac8f4ac1, 0x1b693662, 0x8a432203, 0xf91d0da4, 0x67f6f945,
325                 0xd6d0e4e6, 0x45aad087, 0xb484bc28 } ,
326         { 0x235ea7c9, 0x9238936a, 0x01127f0b, 0x6fec6aac, 0xdec6564d,
327                 0x4da041ee, 0xbc7a2d8f, 0x2b541930 } ,
328         { 0x9a2e04d1, 0x0907f072, 0x77e1dc13, 0xe6bbc7b4, 0x5595b355,
329                 0xc46f9ef6, 0x33498a97, 0xa2237638 } ,
330         { 0x10fd61d9, 0x7fd74d7a, 0xeeb1391b, 0x5d8b24bc, 0xcc65105d,
331                 0x3b3efbfe, 0xaa18e79f, 0x18f2d340 } ,
332         { 0x87ccbee1, 0xf6a6aa82, 0x65809623, 0xd45a81c4, 0x43346d65,
333                 0xb20e5906, 0x20e844a7, 0x8fc23048 } ,
334         { 0xfe9c1be9, 0x6d76078a, 0xdc4ff32b, 0x4b29decc, 0xba03ca6d,
335                 0x28ddb60e, 0x97b7a1af, 0x06918d50 } ,
336         { 0x756b78f1, 0xe4456492, 0x531f5033, 0xc1f93bd4, 0x30d32775,
337                 0x9fad1316, 0x0e86feb7, 0x7d60ea58 } ,
338         { 0xec3ad5f9, 0x5b14c19a, 0xc9eead3b, 0x38c898dc, 0xa7a2847d,
339                 0x167c701e, 0x85565bbf, 0xf4304760 } ,
340         { 0x630a3301, 0xd1e41ea2, 0x40be0a43, 0xaf97f5e4, 0x1e71e185,
341                 0x8d4bcd26, 0xfc25b8c7, 0x6affa468 } ,
342         { 0xd9d99009, 0x48b37baa, 0xb78d674b, 0x266752ec, 0x95413e8d,
343                 0x041b2a2e, 0x72f515cf, 0xe1cf0170 } ,
344         { 0x50a8ed11, 0xbf82d8b2, 0x2e5cc453, 0x9d36aff4, 0x0c109b95,
345                 0x7aea8736, 0xe9c472d7, 0x589e5e78 } ,
346         { 0xc7784a19, 0x365235ba, 0xa52c215b, 0x14060cfc, 0x82dff89d,
347                 0xf1b9e43e, 0x6093cfdf, 0xcf6dbb80 } ,
348         { 0x3e47a721, 0xad2192c2, 0x1bfb7e63, 0x8ad56a04, 0xf9af55a5,
349                 0x68894146, 0xd7632ce7, 0x463d1888 } ,
350         { 0xb5170429, 0x23f0efca, 0x92cadb6b, 0x01a4c70c, 0x707eb2ad,
351                 0xdf589e4e, 0x4e3289ef, 0xbd0c7590 } ,
352         { 0x2be66131, 0x9ac04cd2, 0x099a3873, 0x78742414, 0xe74e0fb5,
353                 0x5627fb56, 0xc501e6f7, 0x33dbd298 } ,
354         { 0xa2b5be39, 0x118fa9da, 0x8069957b, 0xef43811c, 0x5e1d6cbd,
355                 0xccf7585e, 0x3bd143ff, 0xaaab2fa0 } ,
356         { 0x19851b41, 0x885f06e2, 0xf738f283, 0x6612de24, 0xd4ecc9c5,
357                 0x43c6b566, 0xb2a0a107, 0x217a8ca8 } ,
358         { 0x90547849, 0xff2e63ea, 0x6e084f8b, 0xdce23b2c, 0x4bbc26cd,
359                 0xba96126e, 0x296ffe0f, 0x9849e9b0 } ,
360         { 0x0723d551, 0x75fdc0f2, 0xe4d7ac93, 0x53b19834, 0xc28b83d5,
361                 0x31656f76, 0xa03f5b17, 0x0f1946b8 }
362 };
363
364 static const u8 Tr[4][8] = {
365         { 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0a } ,
366         { 0x1b, 0x0c, 0x1d, 0x0e, 0x1f, 0x10, 0x01, 0x12 } ,
367         { 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1a } ,
368         { 0x0b, 0x1c, 0x0d, 0x1e, 0x0f, 0x00, 0x11, 0x02 }
369 };
370
371 /* forward octave */
372 static void W(u32 *key, unsigned int i) {
373         u32 I;
374         key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
375         key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
376         key[4] ^= F3(key[5], Tr[i % 4][2], Tm[i][2]);
377         key[3] ^= F1(key[4], Tr[i % 4][3], Tm[i][3]);
378         key[2] ^= F2(key[3], Tr[i % 4][4], Tm[i][4]);
379         key[1] ^= F3(key[2], Tr[i % 4][5], Tm[i][5]);
380         key[0] ^= F1(key[1], Tr[i % 4][6], Tm[i][6]);   
381         key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]);
382 }
383
384 static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
385                         unsigned key_len)
386 {
387         int i;
388         u32 key[8];
389         __be32 p_key[8]; /* padded key */
390         struct cast6_ctx *c = crypto_tfm_ctx(tfm);
391         u32 *flags = &tfm->crt_flags;
392
393         if (key_len % 4 != 0) {
394                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
395                 return -EINVAL;
396         }       
397
398         memset (p_key, 0, 32);
399         memcpy (p_key, in_key, key_len);
400         
401         key[0] = be32_to_cpu(p_key[0]);         /* A */
402         key[1] = be32_to_cpu(p_key[1]);         /* B */
403         key[2] = be32_to_cpu(p_key[2]);         /* C */
404         key[3] = be32_to_cpu(p_key[3]);         /* D */
405         key[4] = be32_to_cpu(p_key[4]);         /* E */
406         key[5] = be32_to_cpu(p_key[5]);         /* F */
407         key[6] = be32_to_cpu(p_key[6]);         /* G */
408         key[7] = be32_to_cpu(p_key[7]);         /* H */
409         
410
411
412         for (i = 0; i < 12; i++) {
413                 W (key, 2 * i);
414                 W (key, 2 * i + 1);
415                 
416                 c->Kr[i][0] = key[0] & 0x1f;
417                 c->Kr[i][1] = key[2] & 0x1f;
418                 c->Kr[i][2] = key[4] & 0x1f;
419                 c->Kr[i][3] = key[6] & 0x1f;
420                 
421                 c->Km[i][0] = key[7];
422                 c->Km[i][1] = key[5];
423                 c->Km[i][2] = key[3];
424                 c->Km[i][3] = key[1];
425         }
426
427         return 0;
428 }
429
430 /*forward quad round*/
431 static void Q (u32 * block, u8 * Kr, u32 * Km) {
432         u32 I;
433         block[2] ^= F1(block[3], Kr[0], Km[0]);
434         block[1] ^= F2(block[2], Kr[1], Km[1]);
435         block[0] ^= F3(block[1], Kr[2], Km[2]);
436         block[3] ^= F1(block[0], Kr[3], Km[3]);         
437 }
438
439 /*reverse quad round*/
440 static void QBAR (u32 * block, u8 * Kr, u32 * Km) {
441         u32 I;
442         block[3] ^= F1(block[0], Kr[3], Km[3]);
443         block[0] ^= F3(block[1], Kr[2], Km[2]);
444         block[1] ^= F2(block[2], Kr[1], Km[1]);
445         block[2] ^= F1(block[3], Kr[0], Km[0]);
446 }
447
448 static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
449 {
450         struct cast6_ctx *c = crypto_tfm_ctx(tfm);
451         const __be32 *src = (const __be32 *)inbuf;
452         __be32 *dst = (__be32 *)outbuf;
453         u32 block[4];
454         u32 * Km; 
455         u8 * Kr;
456
457         block[0] = be32_to_cpu(src[0]);
458         block[1] = be32_to_cpu(src[1]);
459         block[2] = be32_to_cpu(src[2]);
460         block[3] = be32_to_cpu(src[3]);
461
462         Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km);
463         Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km);
464         Km = c->Km[2]; Kr = c->Kr[2]; Q (block, Kr, Km);
465         Km = c->Km[3]; Kr = c->Kr[3]; Q (block, Kr, Km);
466         Km = c->Km[4]; Kr = c->Kr[4]; Q (block, Kr, Km);
467         Km = c->Km[5]; Kr = c->Kr[5]; Q (block, Kr, Km);
468         Km = c->Km[6]; Kr = c->Kr[6]; QBAR (block, Kr, Km);
469         Km = c->Km[7]; Kr = c->Kr[7]; QBAR (block, Kr, Km);
470         Km = c->Km[8]; Kr = c->Kr[8]; QBAR (block, Kr, Km);
471         Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km);
472         Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km);
473         Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km);
474
475         dst[0] = cpu_to_be32(block[0]);
476         dst[1] = cpu_to_be32(block[1]);
477         dst[2] = cpu_to_be32(block[2]);
478         dst[3] = cpu_to_be32(block[3]);
479 }       
480
481 static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) {
482         struct cast6_ctx * c = crypto_tfm_ctx(tfm);
483         const __be32 *src = (const __be32 *)inbuf;
484         __be32 *dst = (__be32 *)outbuf;
485         u32 block[4];
486         u32 * Km; 
487         u8 * Kr;
488
489         block[0] = be32_to_cpu(src[0]);
490         block[1] = be32_to_cpu(src[1]);
491         block[2] = be32_to_cpu(src[2]);
492         block[3] = be32_to_cpu(src[3]);
493
494         Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km);
495         Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km);
496         Km = c->Km[9]; Kr = c->Kr[9]; Q (block, Kr, Km);
497         Km = c->Km[8]; Kr = c->Kr[8]; Q (block, Kr, Km);
498         Km = c->Km[7]; Kr = c->Kr[7]; Q (block, Kr, Km);
499         Km = c->Km[6]; Kr = c->Kr[6]; Q (block, Kr, Km);
500         Km = c->Km[5]; Kr = c->Kr[5]; QBAR (block, Kr, Km);
501         Km = c->Km[4]; Kr = c->Kr[4]; QBAR (block, Kr, Km);
502         Km = c->Km[3]; Kr = c->Kr[3]; QBAR (block, Kr, Km);
503         Km = c->Km[2]; Kr = c->Kr[2]; QBAR (block, Kr, Km);
504         Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km);
505         Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km);
506         
507         dst[0] = cpu_to_be32(block[0]);
508         dst[1] = cpu_to_be32(block[1]);
509         dst[2] = cpu_to_be32(block[2]);
510         dst[3] = cpu_to_be32(block[3]);
511 }       
512
513 static struct crypto_alg alg = {
514         .cra_name = "cast6",
515         .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
516         .cra_blocksize = CAST6_BLOCK_SIZE,
517         .cra_ctxsize = sizeof(struct cast6_ctx),
518         .cra_alignmask = 3,
519         .cra_module = THIS_MODULE,
520         .cra_list = LIST_HEAD_INIT(alg.cra_list),
521         .cra_u = {
522                   .cipher = {
523                              .cia_min_keysize = CAST6_MIN_KEY_SIZE,
524                              .cia_max_keysize = CAST6_MAX_KEY_SIZE,
525                              .cia_setkey = cast6_setkey,
526                              .cia_encrypt = cast6_encrypt,
527                              .cia_decrypt = cast6_decrypt}
528                   }
529 };
530
531 static int __init cast6_mod_init(void)
532 {
533         return crypto_register_alg(&alg);
534 }
535
536 static void __exit cast6_mod_fini(void)
537 {
538         crypto_unregister_alg(&alg);
539 }
540
541 module_init(cast6_mod_init);
542 module_exit(cast6_mod_fini);
543
544 MODULE_LICENSE("GPL");
545 MODULE_DESCRIPTION("Cast6 Cipher Algorithm");