1 | /* $NetBSD: cast128.c,v 1.10 2014/01/01 15:18:57 pgoyette Exp $ */ |
2 | /* $OpenBSD: cast.c,v 1.2 2000/06/06 06:49:47 deraadt Exp $ */ |
3 | |
4 | /* |
5 | * CAST-128 in C |
6 | * Written by Steve Reid <sreid@sea-to-sky.net> |
7 | * 100% Public Domain - no warranty |
8 | * Released 1997.10.11 |
9 | */ |
10 | |
11 | #include <sys/cdefs.h> |
12 | __KERNEL_RCSID(0, "$NetBSD: cast128.c,v 1.10 2014/01/01 15:18:57 pgoyette Exp $" ); |
13 | |
14 | #include <sys/types.h> |
15 | #include <sys/errno.h> |
16 | #include <sys/module.h> |
17 | |
18 | #include <crypto/cast128/cast128.h> |
19 | #include <crypto/cast128/cast128sb.h> |
20 | |
21 | /* Macros to access 8-bit bytes out of a 32-bit word */ |
22 | #define U_INT8_Ta(x) ( (u_int8_t) (x>>24) ) |
23 | #define U_INT8_Tb(x) ( (u_int8_t) ((x>>16)&255) ) |
24 | #define U_INT8_Tc(x) ( (u_int8_t) ((x>>8)&255) ) |
25 | #define U_INT8_Td(x) ( (u_int8_t) ((x)&255) ) |
26 | |
27 | /* Circular left shift */ |
28 | #define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) ) |
29 | |
30 | /* CAST-128 uses three different round functions */ |
31 | #define F1(l, r, i) \ |
32 | t = ROL(key->xkey[i] + r, key->xkey[i+16]); \ |
33 | l ^= ((cast_sbox1[U_INT8_Ta(t)] ^ cast_sbox2[U_INT8_Tb(t)]) - \ |
34 | cast_sbox3[U_INT8_Tc(t)]) + cast_sbox4[U_INT8_Td(t)]; |
35 | #define F2(l, r, i) \ |
36 | t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \ |
37 | l ^= ((cast_sbox1[U_INT8_Ta(t)] - cast_sbox2[U_INT8_Tb(t)]) + \ |
38 | cast_sbox3[U_INT8_Tc(t)]) ^ cast_sbox4[U_INT8_Td(t)]; |
39 | #define F3(l, r, i) \ |
40 | t = ROL(key->xkey[i] - r, key->xkey[i+16]); \ |
41 | l ^= ((cast_sbox1[U_INT8_Ta(t)] + cast_sbox2[U_INT8_Tb(t)]) ^ \ |
42 | cast_sbox3[U_INT8_Tc(t)]) - cast_sbox4[U_INT8_Td(t)]; |
43 | |
44 | |
45 | /***** Encryption Function *****/ |
46 | |
47 | void cast128_encrypt(const cast128_key* key, const u_int8_t* inblock, |
48 | u_int8_t* outblock) |
49 | { |
50 | u_int32_t t, l, r; |
51 | |
52 | /* Get inblock into l,r */ |
53 | l = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) | |
54 | ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3]; |
55 | r = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) | |
56 | ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7]; |
57 | /* Do the work */ |
58 | F1(l, r, 0); |
59 | F2(r, l, 1); |
60 | F3(l, r, 2); |
61 | F1(r, l, 3); |
62 | F2(l, r, 4); |
63 | F3(r, l, 5); |
64 | F1(l, r, 6); |
65 | F2(r, l, 7); |
66 | F3(l, r, 8); |
67 | F1(r, l, 9); |
68 | F2(l, r, 10); |
69 | F3(r, l, 11); |
70 | /* Only do full 16 rounds if key length > 80 bits */ |
71 | if (key->rounds > 12) { |
72 | F1(l, r, 12); |
73 | F2(r, l, 13); |
74 | F3(l, r, 14); |
75 | F1(r, l, 15); |
76 | } |
77 | /* Put l,r into outblock */ |
78 | outblock[0] = U_INT8_Ta(r); |
79 | outblock[1] = U_INT8_Tb(r); |
80 | outblock[2] = U_INT8_Tc(r); |
81 | outblock[3] = U_INT8_Td(r); |
82 | outblock[4] = U_INT8_Ta(l); |
83 | outblock[5] = U_INT8_Tb(l); |
84 | outblock[6] = U_INT8_Tc(l); |
85 | outblock[7] = U_INT8_Td(l); |
86 | /* Wipe clean */ |
87 | t = l = r = 0; |
88 | } |
89 | |
90 | |
91 | /***** Decryption Function *****/ |
92 | |
93 | void cast128_decrypt(const cast128_key* key, const u_int8_t* inblock, |
94 | u_int8_t* outblock) |
95 | { |
96 | u_int32_t t, l, r; |
97 | |
98 | /* Get inblock into l,r */ |
99 | r = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) | |
100 | ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3]; |
101 | l = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) | |
102 | ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7]; |
103 | /* Do the work */ |
104 | /* Only do full 16 rounds if key length > 80 bits */ |
105 | if (key->rounds > 12) { |
106 | F1(r, l, 15); |
107 | F3(l, r, 14); |
108 | F2(r, l, 13); |
109 | F1(l, r, 12); |
110 | } |
111 | F3(r, l, 11); |
112 | F2(l, r, 10); |
113 | F1(r, l, 9); |
114 | F3(l, r, 8); |
115 | F2(r, l, 7); |
116 | F1(l, r, 6); |
117 | F3(r, l, 5); |
118 | F2(l, r, 4); |
119 | F1(r, l, 3); |
120 | F3(l, r, 2); |
121 | F2(r, l, 1); |
122 | F1(l, r, 0); |
123 | /* Put l,r into outblock */ |
124 | outblock[0] = U_INT8_Ta(l); |
125 | outblock[1] = U_INT8_Tb(l); |
126 | outblock[2] = U_INT8_Tc(l); |
127 | outblock[3] = U_INT8_Td(l); |
128 | outblock[4] = U_INT8_Ta(r); |
129 | outblock[5] = U_INT8_Tb(r); |
130 | outblock[6] = U_INT8_Tc(r); |
131 | outblock[7] = U_INT8_Td(r); |
132 | /* Wipe clean */ |
133 | t = l = r = 0; |
134 | } |
135 | |
136 | |
137 | /***** Key Schedual *****/ |
138 | |
139 | void cast128_setkey(cast128_key* key, const u_int8_t* rawkey, int keybytes) |
140 | { |
141 | u_int32_t t[4], z[4], x[4]; |
142 | int i; |
143 | |
144 | /* Set number of rounds to 12 or 16, depending on key length */ |
145 | key->rounds = (keybytes <= 10 ? 12 : 16); |
146 | |
147 | /* Copy key to workspace x */ |
148 | for (i = 0; i < 4; i++) { |
149 | x[i] = 0; |
150 | t[i] = z[i] = 0; /* XXX gcc */ |
151 | if ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24; |
152 | if ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16; |
153 | if ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8; |
154 | if ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3]; |
155 | } |
156 | /* Generate 32 subkeys, four at a time */ |
157 | for (i = 0; i < 32; i+=4) { |
158 | switch (i & 4) { |
159 | case 0: |
160 | t[0] = z[0] = x[0] ^ cast_sbox5[U_INT8_Tb(x[3])] ^ |
161 | cast_sbox6[U_INT8_Td(x[3])] ^ cast_sbox7[U_INT8_Ta(x[3])] ^ |
162 | cast_sbox8[U_INT8_Tc(x[3])] ^ cast_sbox7[U_INT8_Ta(x[2])]; |
163 | t[1] = z[1] = x[2] ^ cast_sbox5[U_INT8_Ta(z[0])] ^ |
164 | cast_sbox6[U_INT8_Tc(z[0])] ^ cast_sbox7[U_INT8_Tb(z[0])] ^ |
165 | cast_sbox8[U_INT8_Td(z[0])] ^ cast_sbox8[U_INT8_Tc(x[2])]; |
166 | t[2] = z[2] = x[3] ^ cast_sbox5[U_INT8_Td(z[1])] ^ |
167 | cast_sbox6[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Tb(z[1])] ^ |
168 | cast_sbox8[U_INT8_Ta(z[1])] ^ cast_sbox5[U_INT8_Tb(x[2])]; |
169 | t[3] = z[3] = x[1] ^ cast_sbox5[U_INT8_Tc(z[2])] ^ |
170 | cast_sbox6[U_INT8_Tb(z[2])] ^ cast_sbox7[U_INT8_Td(z[2])] ^ |
171 | cast_sbox8[U_INT8_Ta(z[2])] ^ cast_sbox6[U_INT8_Td(x[2])]; |
172 | break; |
173 | case 4: |
174 | t[0] = x[0] = z[2] ^ cast_sbox5[U_INT8_Tb(z[1])] ^ |
175 | cast_sbox6[U_INT8_Td(z[1])] ^ cast_sbox7[U_INT8_Ta(z[1])] ^ |
176 | cast_sbox8[U_INT8_Tc(z[1])] ^ cast_sbox7[U_INT8_Ta(z[0])]; |
177 | t[1] = x[1] = z[0] ^ cast_sbox5[U_INT8_Ta(x[0])] ^ |
178 | cast_sbox6[U_INT8_Tc(x[0])] ^ cast_sbox7[U_INT8_Tb(x[0])] ^ |
179 | cast_sbox8[U_INT8_Td(x[0])] ^ cast_sbox8[U_INT8_Tc(z[0])]; |
180 | t[2] = x[2] = z[1] ^ cast_sbox5[U_INT8_Td(x[1])] ^ |
181 | cast_sbox6[U_INT8_Tc(x[1])] ^ cast_sbox7[U_INT8_Tb(x[1])] ^ |
182 | cast_sbox8[U_INT8_Ta(x[1])] ^ cast_sbox5[U_INT8_Tb(z[0])]; |
183 | t[3] = x[3] = z[3] ^ cast_sbox5[U_INT8_Tc(x[2])] ^ |
184 | cast_sbox6[U_INT8_Tb(x[2])] ^ cast_sbox7[U_INT8_Td(x[2])] ^ |
185 | cast_sbox8[U_INT8_Ta(x[2])] ^ cast_sbox6[U_INT8_Td(z[0])]; |
186 | break; |
187 | } |
188 | switch (i & 12) { |
189 | case 0: |
190 | case 12: |
191 | key->xkey[i+0] = cast_sbox5[U_INT8_Ta(t[2])] ^ cast_sbox6[U_INT8_Tb(t[2])] ^ |
192 | cast_sbox7[U_INT8_Td(t[1])] ^ cast_sbox8[U_INT8_Tc(t[1])]; |
193 | key->xkey[i+1] = cast_sbox5[U_INT8_Tc(t[2])] ^ cast_sbox6[U_INT8_Td(t[2])] ^ |
194 | cast_sbox7[U_INT8_Tb(t[1])] ^ cast_sbox8[U_INT8_Ta(t[1])]; |
195 | key->xkey[i+2] = cast_sbox5[U_INT8_Ta(t[3])] ^ cast_sbox6[U_INT8_Tb(t[3])] ^ |
196 | cast_sbox7[U_INT8_Td(t[0])] ^ cast_sbox8[U_INT8_Tc(t[0])]; |
197 | key->xkey[i+3] = cast_sbox5[U_INT8_Tc(t[3])] ^ cast_sbox6[U_INT8_Td(t[3])] ^ |
198 | cast_sbox7[U_INT8_Tb(t[0])] ^ cast_sbox8[U_INT8_Ta(t[0])]; |
199 | break; |
200 | case 4: |
201 | case 8: |
202 | key->xkey[i+0] = cast_sbox5[U_INT8_Td(t[0])] ^ cast_sbox6[U_INT8_Tc(t[0])] ^ |
203 | cast_sbox7[U_INT8_Ta(t[3])] ^ cast_sbox8[U_INT8_Tb(t[3])]; |
204 | key->xkey[i+1] = cast_sbox5[U_INT8_Tb(t[0])] ^ cast_sbox6[U_INT8_Ta(t[0])] ^ |
205 | cast_sbox7[U_INT8_Tc(t[3])] ^ cast_sbox8[U_INT8_Td(t[3])]; |
206 | key->xkey[i+2] = cast_sbox5[U_INT8_Td(t[1])] ^ cast_sbox6[U_INT8_Tc(t[1])] ^ |
207 | cast_sbox7[U_INT8_Ta(t[2])] ^ cast_sbox8[U_INT8_Tb(t[2])]; |
208 | key->xkey[i+3] = cast_sbox5[U_INT8_Tb(t[1])] ^ cast_sbox6[U_INT8_Ta(t[1])] ^ |
209 | cast_sbox7[U_INT8_Tc(t[2])] ^ cast_sbox8[U_INT8_Td(t[2])]; |
210 | break; |
211 | } |
212 | switch (i & 12) { |
213 | case 0: |
214 | key->xkey[i+0] ^= cast_sbox5[U_INT8_Tc(z[0])]; |
215 | key->xkey[i+1] ^= cast_sbox6[U_INT8_Tc(z[1])]; |
216 | key->xkey[i+2] ^= cast_sbox7[U_INT8_Tb(z[2])]; |
217 | key->xkey[i+3] ^= cast_sbox8[U_INT8_Ta(z[3])]; |
218 | break; |
219 | case 4: |
220 | key->xkey[i+0] ^= cast_sbox5[U_INT8_Ta(x[2])]; |
221 | key->xkey[i+1] ^= cast_sbox6[U_INT8_Tb(x[3])]; |
222 | key->xkey[i+2] ^= cast_sbox7[U_INT8_Td(x[0])]; |
223 | key->xkey[i+3] ^= cast_sbox8[U_INT8_Td(x[1])]; |
224 | break; |
225 | case 8: |
226 | key->xkey[i+0] ^= cast_sbox5[U_INT8_Tb(z[2])]; |
227 | key->xkey[i+1] ^= cast_sbox6[U_INT8_Ta(z[3])]; |
228 | key->xkey[i+2] ^= cast_sbox7[U_INT8_Tc(z[0])]; |
229 | key->xkey[i+3] ^= cast_sbox8[U_INT8_Tc(z[1])]; |
230 | break; |
231 | case 12: |
232 | key->xkey[i+0] ^= cast_sbox5[U_INT8_Td(x[0])]; |
233 | key->xkey[i+1] ^= cast_sbox6[U_INT8_Td(x[1])]; |
234 | key->xkey[i+2] ^= cast_sbox7[U_INT8_Ta(x[2])]; |
235 | key->xkey[i+3] ^= cast_sbox8[U_INT8_Tb(x[3])]; |
236 | break; |
237 | } |
238 | if (i >= 16) { |
239 | key->xkey[i+0] &= 31; |
240 | key->xkey[i+1] &= 31; |
241 | key->xkey[i+2] &= 31; |
242 | key->xkey[i+3] &= 31; |
243 | } |
244 | } |
245 | /* Wipe clean */ |
246 | for (i = 0; i < 4; i++) { |
247 | t[i] = x[i] = z[i] = 0; |
248 | } |
249 | } |
250 | |
251 | /* Made in Canada */ |
252 | |
253 | #if defined(_KERNEL) |
254 | |
255 | MODULE(MODULE_CLASS_MISC, cast128, NULL); |
256 | |
257 | static int |
258 | cast128_modcmd(modcmd_t cmd, void *opaque) |
259 | { |
260 | |
261 | switch (cmd) { |
262 | case MODULE_CMD_INIT: |
263 | return 0; |
264 | case MODULE_CMD_FINI: |
265 | return 0; |
266 | default: |
267 | return ENOTTY; |
268 | } |
269 | } |
270 | |
271 | #endif /* defined(KERNEL) */ |
272 | |