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 <linux/init.h>
22 #include <linux/crypto.h>
23 #include <linux/module.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
26 
27 #define CAST6_BLOCK_SIZE 16
28 #define CAST6_MIN_KEY_SIZE 16
29 #define CAST6_MAX_KEY_SIZE 32
30 
31 struct cast6_ctx {
32 	u32 Km[12][4];
33 	u8 Kr[12][4];
34 };
35 
36 #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
37 
38 #define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
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=rol((r),I)),   \
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=rol((r),I)),   \
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 */
W(u32 * key,unsigned int i)372 static inline 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(void * ctx,const u8 * in_key,unsigned key_len,u32 * flags)385 cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags)
386 {
387 	int i;
388 	u32 key[8];
389 	u8 p_key[32]; /* padded key */
390 	struct cast6_ctx *c = (struct cast6_ctx *) ctx;
391 
392 	if (key_len < 16 || key_len > 32 || key_len % 4 != 0) {
393 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
394 		return -EINVAL;
395 	}
396 
397 	memset (p_key, 0, 32);
398 	memcpy (p_key, in_key, key_len);
399 
400 	key[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3];		/* A */
401 	key[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7];		/* B */
402 	key[2] = p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11];		/* C */
403 	key[3] = p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15];	/* D */
404 	key[4] = p_key[16] << 24 | p_key[17] << 16 | p_key[18] << 8 | p_key[19];	/* E */
405 	key[5] = p_key[20] << 24 | p_key[21] << 16 | p_key[22] << 8 | p_key[23];	/* F */
406 	key[6] = p_key[24] << 24 | p_key[25] << 16 | p_key[26] << 8 | p_key[27];	/* G */
407 	key[7] = p_key[28] << 24 | p_key[29] << 16 | p_key[30] << 8 | p_key[31];	/* H */
408 
409 
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*/
Q(u32 * block,u8 * Kr,u32 * Km)430 static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
431 	u32 I;
432 	block[2] ^= F1(block[3], Kr[0], Km[0]);
433 	block[1] ^= F2(block[2], Kr[1], Km[1]);
434 	block[0] ^= F3(block[1], Kr[2], Km[2]);
435 	block[3] ^= F1(block[0], Kr[3], Km[3]);
436 }
437 
438 /*reverse quad round*/
QBAR(u32 * block,u8 * Kr,u32 * Km)439 static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) {
440 	u32 I;
441         block[3] ^= F1(block[0], Kr[3], Km[3]);
442         block[0] ^= F3(block[1], Kr[2], Km[2]);
443         block[1] ^= F2(block[2], Kr[1], Km[1]);
444         block[2] ^= F1(block[3], Kr[0], Km[0]);
445 }
446 
cast6_encrypt(void * ctx,u8 * outbuf,const u8 * inbuf)447 static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
448 	struct cast6_ctx * c = (struct cast6_ctx *)ctx;
449 	u32 block[4];
450 	u32 * Km;
451 	u8 * Kr;
452 
453 	block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
454 	block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
455 	block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11];
456 	block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15];
457 
458 	Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km);
459 	Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km);
460 	Km = c->Km[2]; Kr = c->Kr[2]; Q (block, Kr, Km);
461 	Km = c->Km[3]; Kr = c->Kr[3]; Q (block, Kr, Km);
462 	Km = c->Km[4]; Kr = c->Kr[4]; Q (block, Kr, Km);
463 	Km = c->Km[5]; Kr = c->Kr[5]; Q (block, Kr, Km);
464 	Km = c->Km[6]; Kr = c->Kr[6]; QBAR (block, Kr, Km);
465 	Km = c->Km[7]; Kr = c->Kr[7]; QBAR (block, Kr, Km);
466 	Km = c->Km[8]; Kr = c->Kr[8]; QBAR (block, Kr, Km);
467 	Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km);
468 	Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km);
469 	Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km);
470 
471 	outbuf[0] = (block[0] >> 24) & 0xff;
472 	outbuf[1] = (block[0] >> 16) & 0xff;
473 	outbuf[2] = (block[0] >> 8) & 0xff;
474 	outbuf[3] = block[0] & 0xff;
475 	outbuf[4] = (block[1] >> 24) & 0xff;
476 	outbuf[5] = (block[1] >> 16) & 0xff;
477 	outbuf[6] = (block[1] >> 8) & 0xff;
478 	outbuf[7] = block[1] & 0xff;
479 	outbuf[8] = (block[2] >> 24) & 0xff;
480 	outbuf[9] = (block[2] >> 16) & 0xff;
481 	outbuf[10] = (block[2] >> 8) & 0xff;
482 	outbuf[11] = block[2] & 0xff;
483 	outbuf[12] = (block[3] >> 24) & 0xff;
484 	outbuf[13] = (block[3] >> 16) & 0xff;
485 	outbuf[14] = (block[3] >> 8) & 0xff;
486 	outbuf[15] = block[3] & 0xff;
487 }
488 
cast6_decrypt(void * ctx,u8 * outbuf,const u8 * inbuf)489 static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
490 	struct cast6_ctx * c = (struct cast6_ctx *)ctx;
491 	u32 block[4];
492 	u32 * Km;
493 	u8 * Kr;
494 
495 	block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
496 	block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
497 	block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11];
498 	block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15];
499 
500 	Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km);
501 	Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km);
502 	Km = c->Km[9]; Kr = c->Kr[9]; Q (block, Kr, Km);
503 	Km = c->Km[8]; Kr = c->Kr[8]; Q (block, Kr, Km);
504 	Km = c->Km[7]; Kr = c->Kr[7]; Q (block, Kr, Km);
505 	Km = c->Km[6]; Kr = c->Kr[6]; Q (block, Kr, Km);
506 	Km = c->Km[5]; Kr = c->Kr[5]; QBAR (block, Kr, Km);
507 	Km = c->Km[4]; Kr = c->Kr[4]; QBAR (block, Kr, Km);
508 	Km = c->Km[3]; Kr = c->Kr[3]; QBAR (block, Kr, Km);
509 	Km = c->Km[2]; Kr = c->Kr[2]; QBAR (block, Kr, Km);
510 	Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km);
511 	Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km);
512 
513 	outbuf[0] = (block[0] >> 24) & 0xff;
514 	outbuf[1] = (block[0] >> 16) & 0xff;
515 	outbuf[2] = (block[0] >> 8) & 0xff;
516 	outbuf[3] = block[0] & 0xff;
517 	outbuf[4] = (block[1] >> 24) & 0xff;
518 	outbuf[5] = (block[1] >> 16) & 0xff;
519 	outbuf[6] = (block[1] >> 8) & 0xff;
520 	outbuf[7] = block[1] & 0xff;
521 	outbuf[8] = (block[2] >> 24) & 0xff;
522 	outbuf[9] = (block[2] >> 16) & 0xff;
523 	outbuf[10] = (block[2] >> 8) & 0xff;
524 	outbuf[11] = block[2] & 0xff;
525 	outbuf[12] = (block[3] >> 24) & 0xff;
526 	outbuf[13] = (block[3] >> 16) & 0xff;
527 	outbuf[14] = (block[3] >> 8) & 0xff;
528 	outbuf[15] = block[3] & 0xff;
529 }
530 
531 static struct crypto_alg alg = {
532 	.cra_name = "cast6",
533 	.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
534 	.cra_blocksize = CAST6_BLOCK_SIZE,
535 	.cra_ctxsize = sizeof(struct cast6_ctx),
536 	.cra_module = THIS_MODULE,
537 	.cra_list = LIST_HEAD_INIT(alg.cra_list),
538 	.cra_u = {
539 		  .cipher = {
540 			     .cia_min_keysize = CAST6_MIN_KEY_SIZE,
541 			     .cia_max_keysize = CAST6_MAX_KEY_SIZE,
542 			     .cia_setkey = cast6_setkey,
543 			     .cia_encrypt = cast6_encrypt,
544 			     .cia_decrypt = cast6_decrypt}
545 		  }
546 };
547 
init(void)548 static int __init init(void)
549 {
550 	return crypto_register_alg(&alg);
551 }
552 
fini(void)553 static void __exit fini(void)
554 {
555 	crypto_unregister_alg(&alg);
556 }
557 
558 module_init(init);
559 module_exit(fini);
560 
561 MODULE_LICENSE("GPL");
562 MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
563