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