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
47void cast128_encrypt(const cast128_key* key, const u_int8_t* inblock,
48 u_int8_t* outblock)
49{
50u_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
93void cast128_decrypt(const cast128_key* key, const u_int8_t* inblock,
94 u_int8_t* outblock)
95{
96u_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
139void 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
255MODULE(MODULE_CLASS_MISC, cast128, NULL);
256
257static int
258cast128_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