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
33struct 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
45static 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
112static 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
179static 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
246static 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
313static 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
364static 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 */
372static void W(u32 *key, unsigned int i)
373{
374	u32 I;
375	key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
376	key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
377	key[4] ^= F3(key[5], Tr[i % 4][2], Tm[i][2]);
378	key[3] ^= F1(key[4], Tr[i % 4][3], Tm[i][3]);
379	key[2] ^= F2(key[3], Tr[i % 4][4], Tm[i][4]);
380	key[1] ^= F3(key[2], Tr[i % 4][5], Tm[i][5]);
381	key[0] ^= F1(key[1], Tr[i % 4][6], Tm[i][6]);
382	key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]);
383}
384
385static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
386			unsigned key_len)
387{
388	int i;
389	u32 key[8];
390	__be32 p_key[8]; /* padded key */
391	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
392	u32 *flags = &tfm->crt_flags;
393
394	if (key_len % 4 != 0) {
395		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
396		return -EINVAL;
397	}
398
399	memset(p_key, 0, 32);
400	memcpy(p_key, in_key, key_len);
401
402	key[0] = be32_to_cpu(p_key[0]);		/* A */
403	key[1] = be32_to_cpu(p_key[1]);		/* B */
404	key[2] = be32_to_cpu(p_key[2]);		/* C */
405	key[3] = be32_to_cpu(p_key[3]);		/* D */
406	key[4] = be32_to_cpu(p_key[4]);		/* E */
407	key[5] = be32_to_cpu(p_key[5]);		/* F */
408	key[6] = be32_to_cpu(p_key[6]);		/* G */
409	key[7] = be32_to_cpu(p_key[7]);		/* H */
410
411	for (i = 0; i < 12; i++) {
412		W(key, 2 * i);
413		W(key, 2 * i + 1);
414
415		c->Kr[i][0] = key[0] & 0x1f;
416		c->Kr[i][1] = key[2] & 0x1f;
417		c->Kr[i][2] = key[4] & 0x1f;
418		c->Kr[i][3] = key[6] & 0x1f;
419
420		c->Km[i][0] = key[7];
421		c->Km[i][1] = key[5];
422		c->Km[i][2] = key[3];
423		c->Km[i][3] = key[1];
424	}
425
426	return 0;
427}
428
429/*forward quad round*/
430static void Q(u32 *block, u8 *Kr, u32 *Km)
431{
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*/
440static void QBAR(u32 *block, u8 *Kr, u32 *Km)
441{
442	u32 I;
443	block[3] ^= F1(block[0], Kr[3], Km[3]);
444	block[0] ^= F3(block[1], Kr[2], Km[2]);
445	block[1] ^= F2(block[2], Kr[1], Km[1]);
446	block[2] ^= F1(block[3], Kr[0], Km[0]);
447}
448
449static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
450{
451	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
452	const __be32 *src = (const __be32 *)inbuf;
453	__be32 *dst = (__be32 *)outbuf;
454	u32 block[4];
455	u32 *Km;
456	u8 *Kr;
457
458	block[0] = be32_to_cpu(src[0]);
459	block[1] = be32_to_cpu(src[1]);
460	block[2] = be32_to_cpu(src[2]);
461	block[3] = be32_to_cpu(src[3]);
462
463	Km = c->Km[0]; Kr = c->Kr[0]; Q(block, Kr, Km);
464	Km = c->Km[1]; Kr = c->Kr[1]; Q(block, Kr, Km);
465	Km = c->Km[2]; Kr = c->Kr[2]; Q(block, Kr, Km);
466	Km = c->Km[3]; Kr = c->Kr[3]; Q(block, Kr, Km);
467	Km = c->Km[4]; Kr = c->Kr[4]; Q(block, Kr, Km);
468	Km = c->Km[5]; Kr = c->Kr[5]; Q(block, Kr, Km);
469	Km = c->Km[6]; Kr = c->Kr[6]; QBAR(block, Kr, Km);
470	Km = c->Km[7]; Kr = c->Kr[7]; QBAR(block, Kr, Km);
471	Km = c->Km[8]; Kr = c->Kr[8]; QBAR(block, Kr, Km);
472	Km = c->Km[9]; Kr = c->Kr[9]; QBAR(block, Kr, Km);
473	Km = c->Km[10]; Kr = c->Kr[10]; QBAR(block, Kr, Km);
474	Km = c->Km[11]; Kr = c->Kr[11]; QBAR(block, Kr, Km);
475
476	dst[0] = cpu_to_be32(block[0]);
477	dst[1] = cpu_to_be32(block[1]);
478	dst[2] = cpu_to_be32(block[2]);
479	dst[3] = cpu_to_be32(block[3]);
480}
481
482static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
483{
484	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
485	const __be32 *src = (const __be32 *)inbuf;
486	__be32 *dst = (__be32 *)outbuf;
487	u32 block[4];
488	u32 *Km;
489	u8 *Kr;
490
491	block[0] = be32_to_cpu(src[0]);
492	block[1] = be32_to_cpu(src[1]);
493	block[2] = be32_to_cpu(src[2]);
494	block[3] = be32_to_cpu(src[3]);
495
496	Km = c->Km[11]; Kr = c->Kr[11]; Q(block, Kr, Km);
497	Km = c->Km[10]; Kr = c->Kr[10]; Q(block, Kr, Km);
498	Km = c->Km[9]; Kr = c->Kr[9]; Q(block, Kr, Km);
499	Km = c->Km[8]; Kr = c->Kr[8]; Q(block, Kr, Km);
500	Km = c->Km[7]; Kr = c->Kr[7]; Q(block, Kr, Km);
501	Km = c->Km[6]; Kr = c->Kr[6]; Q(block, Kr, Km);
502	Km = c->Km[5]; Kr = c->Kr[5]; QBAR(block, Kr, Km);
503	Km = c->Km[4]; Kr = c->Kr[4]; QBAR(block, Kr, Km);
504	Km = c->Km[3]; Kr = c->Kr[3]; QBAR(block, Kr, Km);
505	Km = c->Km[2]; Kr = c->Kr[2]; QBAR(block, Kr, Km);
506	Km = c->Km[1]; Kr = c->Kr[1]; QBAR(block, Kr, Km);
507	Km = c->Km[0]; Kr = c->Kr[0]; QBAR(block, Kr, Km);
508
509	dst[0] = cpu_to_be32(block[0]);
510	dst[1] = cpu_to_be32(block[1]);
511	dst[2] = cpu_to_be32(block[2]);
512	dst[3] = cpu_to_be32(block[3]);
513}
514
515static struct crypto_alg alg = {
516	.cra_name = "cast6",
517	.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
518	.cra_blocksize = CAST6_BLOCK_SIZE,
519	.cra_ctxsize = sizeof(struct cast6_ctx),
520	.cra_alignmask = 3,
521	.cra_module = THIS_MODULE,
522	.cra_list = LIST_HEAD_INIT(alg.cra_list),
523	.cra_u = {
524		  .cipher = {
525			     .cia_min_keysize = CAST6_MIN_KEY_SIZE,
526			     .cia_max_keysize = CAST6_MAX_KEY_SIZE,
527			     .cia_setkey = cast6_setkey,
528			     .cia_encrypt = cast6_encrypt,
529			     .cia_decrypt = cast6_decrypt}
530		  }
531};
532
533static int __init cast6_mod_init(void)
534{
535	return crypto_register_alg(&alg);
536}
537
538static void __exit cast6_mod_fini(void)
539{
540	crypto_unregister_alg(&alg);
541}
542
543module_init(cast6_mod_init);
544module_exit(cast6_mod_fini);
545
546MODULE_LICENSE("GPL");
547MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
548