linux-warning-reduction-20090318
[openafs.git] / src / rxkad / bg-fcrypt.c
1 /*
2  * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include <afsconfig.h>
34 #ifdef KERNEL
35 #include "afs/param.h"
36 #else
37 #include <afs/param.h>
38 #endif
39
40 RCSID
41     ("$Header$");
42
43 #define DEBUG 0
44 #ifdef KERNEL
45 #ifndef UKERNEL
46 #include "afs/stds.h"
47 #include "h/types.h"
48 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_OBSD_ENV)
49 #include "netinet/in.h"
50 #endif
51 #else /* UKERNEL */
52 #include "afs/sysincludes.h"
53 #include "afs/stds.h"
54 #endif /* UKERNEL */
55 #ifdef AFS_LINUX22_ENV
56 #include <asm/byteorder.h>
57 #endif
58
59 #else /* KERNEL */
60
61 #include <afs/stds.h>
62 #include <sys/types.h>
63 #ifdef AFS_NT40_ENV
64 #include <winsock2.h>
65 #else
66 #include <netinet/in.h>
67 #endif
68 #include <rx/rx.h>
69 #endif /* KERNEL */
70
71 #include "fcrypt.h"
72 #include "rxkad.h"
73 #include "fcrypt.h"
74 #include "private_data.h"
75 #include <des/stats.h>
76
77 /*
78  * Unrolling of the inner loops helps the most on pentium chips
79  * (ca 18%). On risc machines only expect a modest improvement (ca 5%).
80  * The cost for this is rougly 4k bytes.
81  */
82 #define UNROLL_LOOPS 1
83 /*
84  * Inline assembler gives a boost only to fc_keysched.
85  * On the pentium expect ca 28%.
86  */
87 /*#define GNU_ASM 1 (now autoconfed) */
88
89 #if !defined(inline) && !defined(__GNUC__)
90 #define inline
91 #endif
92
93 /*
94  * There is usually no memcpy in kernels but gcc will inline all
95  * calls to memcpy in this code anyway.
96  */
97 #if defined(KERNEL) && !defined(__GNUC__)
98 #define memcpy(to, from, n) bcopy((from), (to), (n))
99 #endif
100
101 /* Rotate 32 bit word left */
102 #define ROT32L(x, n) ((((afs_uint32) x) << (n)) | (((afs_uint32) x) >> (32-(n))))
103 #define bswap32(x) (((ROT32L(x, 16) & 0x00ff00ff)<<8) | ((ROT32L(x, 16)>>8) & 0x00ff00ff))
104
105 #if WORDS_BIGENDIAN
106 #define NTOH(x) (x)
107 #else
108 #define NTOH(x) bswap32(x)
109 #endif
110
111 /*
112  * Try to use a good function for ntohl-ing.
113  *
114  * The choice is done by autoconf setting EFF_NTOHL to one of:
115  * CPU          function
116  * i386         ntohl
117  * i[4-9]86     bswap
118  * alpha        bswap32
119  * all else     ntohl
120  */
121
122 #define EFF_NTOHL(x) ntohl(x)
123
124 #if 0
125 #if defined(__GNUC__) && (defined(i386) || defined(__i386__))
126 static inline afs_uint32
127 bswap(afs_uint32 x)
128 {
129   asm("bswap %0": "=r"(x):"0"(x));
130     return x;
131 }
132 #endif
133 #endif
134
135 /*
136  * Sboxes for Feistel network derived from
137  * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
138  */
139
140 #undef Z
141 #define Z(x) NTOH(x << 3)
142 static const afs_uint32 sbox0[256] = {
143     Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
144     Z(0xcd), Z(0x86), Z(0x86),
145     Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06), Z(0x0e), Z(0x06), Z(0xd2),
146     Z(0x65), Z(0x73), Z(0xc5),
147     Z(0x28), Z(0x60), Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda),
148     Z(0x9f), Z(0xe3), Z(0xd2),
149     Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a), Z(0x35),
150     Z(0xac), Z(0xaa), Z(0x5f),
151     Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53), Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3),
152     Z(0xdc), Z(0x09), Z(0x32),
153     Z(0x10), Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf),
154     Z(0xfd), Z(0x3b), Z(0x95),
155     Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80), Z(0x9c), Z(0xf3),
156     Z(0xec), Z(0xda), Z(0x9f),
157     Z(0x26), Z(0x76), Z(0x15), Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84),
158     Z(0xee), Z(0xad), Z(0xc7),
159     Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
160     Z(0x0b), Z(0x8a), Z(0x83),
161     Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8), Z(0xb1), Z(0xd4), Z(0x01),
162     Z(0xd8), Z(0x70), Z(0x64),
163     Z(0xf0), Z(0x51), Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5),
164     Z(0x64), Z(0xef), Z(0x10),
165     Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44), Z(0x3d),
166     Z(0xe5), Z(0xb3), Z(0x5b),
167     Z(0xae), Z(0xd5), Z(0xad), Z(0x1d), Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33),
168     Z(0xab), Z(0x93), Z(0xa2),
169     Z(0xb7), Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63),
170     Z(0x44), Z(0xb6), Z(0x69),
171     Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0), Z(0x17), Z(0xbb),
172     Z(0xc7), Z(0xf3), Z(0x3f),
173     Z(0x36), Z(0xba), Z(0x71), Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69),
174     Z(0xb6), Z(0xf6), Z(0xe6),
175     Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
176     Z(0x22), Z(0x99), Z(0xfd),
177     Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1), Z(0xb6), Z(0x5b), Z(0xae),
178     Z(0x54), Z(0xb3), Z(0x70),
179     Z(0xff), Z(0xc6), Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e),
180     Z(0x76), Z(0xe5), Z(0x36),
181     Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6), Z(0x93),
182     Z(0xc4), Z(0xaa), Z(0x26),
183     Z(0x49), Z(0xe0), Z(0x21), Z(0x64), Z(0x07), Z(0x9f), Z(0x64), Z(0x81),
184     Z(0x9c), Z(0xbf), Z(0xf9),
185     Z(0xd1), Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75),
186     Z(0x03), Z(0xe4), Z(0xb0),
187     Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39), Z(0x72), Z(0x12),
188     Z(0xf6), Z(0xba), Z(0x0c),
189     Z(0x0d), Z(0x42), Z(0x2e)
190 };
191
192 #undef Z
193 #define Z(x) NTOH((x << 27) | (x >> 5))
194 static const afs_uint32 sbox1[256] = {
195     Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
196     Z(0x67), Z(0x6c), Z(0xa1),
197     Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85), Z(0x6c), Z(0x7b), Z(0x67),
198     Z(0xc6), Z(0x23), Z(0xe3),
199     Z(0xf2), Z(0x89), Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6),
200     Z(0xe1), Z(0x39), Z(0x31),
201     Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6), Z(0x23),
202     Z(0x83), Z(0x98), Z(0x7d),
203     Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99), Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20),
204     Z(0x03), Z(0x7c), Z(0x5f),
205     Z(0xad), Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd),
206     Z(0xb6), Z(0xb8), Z(0xa1),
207     Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b), Z(0x16), Z(0x74),
208     Z(0x31), Z(0x8a), Z(0x23),
209     Z(0x17), Z(0x04), Z(0xfa), Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13),
210     Z(0xab), Z(0xb5), Z(0x2e),
211     Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
212     Z(0xe2), Z(0xaf), Z(0x45),
213     Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd), Z(0x00), Z(0x92), Z(0x7d),
214     Z(0x97), Z(0x7a), Z(0x18),
215     Z(0x60), Z(0x3d), Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6),
216     Z(0xbb), Z(0x8b), Z(0x06),
217     Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17), Z(0x89),
218     Z(0xd0), Z(0xa9), Z(0xc1),
219     Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5), Z(0x43), Z(0xf4), Z(0x68), Z(0xc8),
220     Z(0xd3), Z(0x84), Z(0x28),
221     Z(0x0a), Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f),
222     Z(0x7a), Z(0x31), Z(0xf7),
223     Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5), Z(0x24), Z(0x66),
224     Z(0xfc), Z(0xb3), Z(0x57),
225     Z(0x25), Z(0xbe), Z(0x89), Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23),
226     Z(0x3c), Z(0x12), Z(0x52),
227     Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
228     Z(0x69), Z(0x10), Z(0x9d),
229     Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30), Z(0x05), Z(0x5e), Z(0x32),
230     Z(0xc0), Z(0xd5), Z(0x19),
231     Z(0xbd), Z(0x45), Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c),
232     Z(0xa9), Z(0x96), Z(0xef),
233     Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad), Z(0x80),
234     Z(0x48), Z(0x81), Z(0xb7),
235     Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7), Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a),
236     Z(0x59), Z(0x7c), Z(0x57),
237     Z(0xc1), Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4),
238     Z(0x78), Z(0x16), Z(0x06),
239     Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4), Z(0x70), Z(0x03),
240     Z(0xe0), Z(0x2f), Z(0x96),
241     Z(0x91), Z(0x82), Z(0x80)
242 };
243
244 #undef Z
245 #define Z(x) NTOH(x << 11)
246 static const afs_uint32 sbox2[256] = {
247     Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
248     Z(0xd1), Z(0xec), Z(0x50),
249     Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d), Z(0xbf), Z(0x80), Z(0x87),
250     Z(0x27), Z(0x95), Z(0xe2),
251     Z(0xc5), Z(0x5d), Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e),
252     Z(0xe7), Z(0x24), Z(0xc8),
253     Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9), Z(0xe8),
254     Z(0xdc), Z(0xb7), Z(0xd9),
255     Z(0x45), Z(0x20), Z(0x1b), Z(0xce), Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd),
256     Z(0x0e), Z(0x8f), Z(0xa3),
257     Z(0xa9), Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1),
258     Z(0x68), Z(0x84), Z(0xbc),
259     Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6), Z(0x13), Z(0x5e),
260     Z(0x07), Z(0xb8), Z(0x95),
261     Z(0x02), Z(0xc0), Z(0xd0), Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6),
262     Z(0xfd), Z(0xfe), Z(0x17),
263     Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
264     Z(0x6d), Z(0x1c), Z(0x6c),
265     Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e), Z(0x8b), Z(0x6b), Z(0xbe),
266     Z(0x29), Z(0xeb), Z(0x12),
267     Z(0x19), Z(0x34), Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b),
268     Z(0xd5), Z(0xae), Z(0x2a),
269     Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc), Z(0x2c),
270     Z(0xd0), Z(0x22), Z(0x4b),
271     Z(0xb1), Z(0x85), Z(0x59), Z(0x80), Z(0xc0), Z(0x30), Z(0x9f), Z(0x73),
272     Z(0xd3), Z(0x14), Z(0x48),
273     Z(0x40), Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b),
274     Z(0x5e), Z(0xb7), Z(0x5e),
275     Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15), Z(0x05), Z(0xe8),
276     Z(0x02), Z(0x77), Z(0xa9),
277     Z(0xc7), Z(0x40), Z(0x45), Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c),
278     Z(0x79), Z(0x2a), Z(0x99),
279     Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
280     Z(0xdc), Z(0xff), Z(0xfd),
281     Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a), Z(0xec), Z(0x8e), Z(0x19),
282     Z(0x18), Z(0xb4), Z(0x6e),
283     Z(0x3d), Z(0xfd), Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8),
284     Z(0xbc), Z(0x1f), Z(0x56),
285     Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5), Z(0xf3),
286     Z(0x8e), Z(0xde), Z(0xae),
287     Z(0x37), Z(0x49), Z(0xb7), Z(0xfa), Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0),
288     Z(0x2a), Z(0x9b), Z(0x15),
289     Z(0xd1), Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84),
290     Z(0x59), Z(0x56), Z(0x68),
291     Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f), Z(0x8c), Z(0x8a),
292     Z(0x73), Z(0x80), Z(0x76),
293     Z(0xb4), Z(0x10), Z(0x86)
294 };
295
296 #undef Z
297 #define Z(x) NTOH(x << 19)
298 static const afs_uint32 sbox3[256] = {
299     Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
300     Z(0xb5), Z(0xb7), Z(0x42),
301     Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12), Z(0x44), Z(0x48), Z(0x6d),
302     Z(0x28), Z(0xaa), Z(0x20),
303     Z(0x6d), Z(0x57), Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92),
304     Z(0x5a), Z(0x1b), Z(0x53),
305     Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66), Z(0xa1),
306     Z(0x01), Z(0xa5), Z(0x41),
307     Z(0x97), Z(0x41), Z(0x31), Z(0x82), Z(0xf1), Z(0x14), Z(0xcf), Z(0x53),
308     Z(0x0d), Z(0xa0), Z(0x10),
309     Z(0xcc), Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb),
310     Z(0x16), Z(0x47), Z(0xf6),
311     Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a), Z(0xa7), Z(0xdf),
312     Z(0x29), Z(0x43), Z(0x01),
313     Z(0x54), Z(0x70), Z(0xa4), Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44),
314     Z(0x60), Z(0x9e), Z(0x23),
315     Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
316     Z(0x2a), Z(0x41), Z(0xb2),
317     Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d), Z(0x13), Z(0x3a), Z(0x3c),
318     Z(0x6e), Z(0x35), Z(0xdc),
319     Z(0x60), Z(0x65), Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f),
320     Z(0x9f), Z(0x87), Z(0x96),
321     Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4), Z(0x5a),
322     Z(0x83), Z(0xbf), Z(0x92),
323     Z(0x1b), Z(0x94), Z(0x00), Z(0x42), Z(0xcf), Z(0x4b), Z(0x00), Z(0x75),
324     Z(0xba), Z(0x8f), Z(0x76),
325     Z(0x5f), Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38),
326     Z(0x95), Z(0x17), Z(0xe4),
327     Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85), Z(0x82), Z(0x4c),
328     Z(0x9d), Z(0x2f), Z(0x3b),
329     Z(0x66), Z(0xa1), Z(0x34), Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5),
330     Z(0x31), Z(0xcf), Z(0x05),
331     Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
332     Z(0x19), Z(0xf1), Z(0xa1),
333     Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0), Z(0x98), Z(0x8d), Z(0x0b),
334     Z(0x23), Z(0xc3), Z(0x3a),
335     Z(0x2d), Z(0x20), Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d),
336     Z(0x6c), Z(0x2f), Z(0x47),
337     Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79), Z(0x3d),
338     Z(0xa2), Z(0x54), Z(0xbd),
339     Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3), Z(0x05), Z(0x28), Z(0xf1), Z(0x16),
340     Z(0x46), Z(0x40), Z(0xb0),
341     Z(0x11), Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d),
342     Z(0x8f), Z(0xd8), Z(0xe1),
343     Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9), Z(0xa1), Z(0xc2),
344     Z(0xc5), Z(0xe3), Z(0xba),
345     Z(0xfc), Z(0x0e), Z(0x25)
346 };
347
348 /*
349  * This is a 16 round Feistel network with permutation F_ENCRYPT
350  */
351
352 #define F_ENCRYPT(R, L, sched) { \
353  union lc4 { afs_uint32 l; unsigned char c[4]; } un; \
354  un.l = sched ^ R; \
355  L ^= sbox0[un.c[0]] ^ sbox1[un.c[1]] ^ sbox2[un.c[2]] ^ sbox3[un.c[3]]; }
356
357 #ifndef WORDS_BIGENDIAN
358 /* BEWARE: this code is endian dependent.
359  * This should really be inline assembler on the x86.
360  */
361 #undef F_ENCRYPT
362 #define FF(y, shiftN) (((y) >> shiftN) & 0xFF)
363 #define F_ENCRYPT(R, L, sched) { \
364  afs_uint32 un; \
365  un = sched ^ R; \
366  L ^= sbox0[FF(un, 0)] ^ sbox1[FF(un, 8)] ^ sbox2[FF(un, 16)] ^ sbox3[FF(un, 24)];}
367 #endif
368
369 static inline void
370 fc_ecb_enc(afs_uint32 l, afs_uint32 r, afs_uint32 out[2],
371            const afs_int32 sched[MAXROUNDS])
372 {
373 #if !defined(UNROLL_LOOPS)
374     {
375         int i;
376         for (i = 0; i < (MAXROUNDS / 4); i++) {
377             F_ENCRYPT(r, l, *sched++);
378             F_ENCRYPT(l, r, *sched++);
379             F_ENCRYPT(r, l, *sched++);
380             F_ENCRYPT(l, r, *sched++);
381         }
382     }
383 #else
384     F_ENCRYPT(r, l, *sched++);
385     F_ENCRYPT(l, r, *sched++);
386     F_ENCRYPT(r, l, *sched++);
387     F_ENCRYPT(l, r, *sched++);
388     F_ENCRYPT(r, l, *sched++);
389     F_ENCRYPT(l, r, *sched++);
390     F_ENCRYPT(r, l, *sched++);
391     F_ENCRYPT(l, r, *sched++);
392     F_ENCRYPT(r, l, *sched++);
393     F_ENCRYPT(l, r, *sched++);
394     F_ENCRYPT(r, l, *sched++);
395     F_ENCRYPT(l, r, *sched++);
396     F_ENCRYPT(r, l, *sched++);
397     F_ENCRYPT(l, r, *sched++);
398     F_ENCRYPT(r, l, *sched++);
399     F_ENCRYPT(l, r, *sched++);
400 #endif /* UNROLL_LOOPS */
401
402     out[0] = l;
403     out[1] = r;
404 }
405
406 static inline void
407 fc_ecb_dec(afs_uint32 l, afs_uint32 r, afs_uint32 out[2],
408            const afs_int32 sched[MAXROUNDS])
409 {
410     sched = &sched[MAXROUNDS - 1];
411
412 #if !defined(UNROLL_LOOPS)
413     {
414         int i;
415         for (i = 0; i < (MAXROUNDS / 4); i++) {
416             F_ENCRYPT(l, r, *sched--);
417             F_ENCRYPT(r, l, *sched--);
418             F_ENCRYPT(l, r, *sched--);
419             F_ENCRYPT(r, l, *sched--);
420         }
421     }
422 #else
423     F_ENCRYPT(l, r, *sched--);
424     F_ENCRYPT(r, l, *sched--);
425     F_ENCRYPT(l, r, *sched--);
426     F_ENCRYPT(r, l, *sched--);
427     F_ENCRYPT(l, r, *sched--);
428     F_ENCRYPT(r, l, *sched--);
429     F_ENCRYPT(l, r, *sched--);
430     F_ENCRYPT(r, l, *sched--);
431     F_ENCRYPT(l, r, *sched--);
432     F_ENCRYPT(r, l, *sched--);
433     F_ENCRYPT(l, r, *sched--);
434     F_ENCRYPT(r, l, *sched--);
435     F_ENCRYPT(l, r, *sched--);
436     F_ENCRYPT(r, l, *sched--);
437     F_ENCRYPT(l, r, *sched--);
438     F_ENCRYPT(r, l, *sched--);
439 #endif /* UNROLL_LOOPS */
440
441     out[0] = l;
442     out[1] = r;
443 }
444
445 static inline void
446 fc_cbc_enc(const afs_uint32 * in, afs_uint32 * out, afs_int32 length,
447            const afs_int32 sched[MAXROUNDS], afs_uint32 * iv)
448 {
449     afs_int32 xor0 = iv[0], xor1 = iv[1];
450
451     for (; length > 0; length -= 8) {
452         afs_uint32 b8[2];
453         /* If length < 8 we read to much, usally ok */
454         xor0 ^= in[0];
455         xor1 ^= in[1];
456         fc_ecb_enc(xor0, xor1, b8, sched);
457         xor0 = in[0] ^ b8[0];
458         xor1 = in[1] ^ b8[1];
459
460         /* Out is always a multiple of 8 */
461         memcpy(out, b8, 8);
462         out += 2;
463         in += 2;
464     }
465     iv[0] = xor0;
466     iv[1] = xor1;
467 }
468
469 static inline void
470 fc_cbc_dec(const afs_uint32 * in, afs_uint32 * out, afs_int32 length,
471            const afs_int32 sched[MAXROUNDS], afs_uint32 * iv)
472 {
473     afs_int32 xor0 = iv[0], xor1 = iv[1];
474
475     for (; length > 0; length -= 8) {
476         afs_uint32 b8[2];
477         /* In is always a multiple of 8 */
478         fc_ecb_dec(in[0], in[1], b8, sched);
479         b8[0] ^= xor0;
480         b8[1] ^= xor1;
481         xor0 = in[0] ^ b8[0];
482         xor1 = in[1] ^ b8[1];
483
484 #if 0
485         if (length >= 8)
486             memcpy(out, b8, 8);
487         else
488             memcpy(out, b8, length);    /* Don't write to much when length < 8 */
489 #else
490         /* If length < 8 we write to much, this is not always ok */
491         memcpy(out, b8, 8);
492 #endif
493         out += 2;
494         in += 2;
495     }
496     iv[0] = xor0;
497     iv[1] = xor1;
498 }
499
500 afs_int32
501 fc_ecb_encrypt(afs_uint32 * in, afs_uint32 * out, fc_KeySchedule sched,
502                int encrypt)
503 {
504     INC_RXKAD_STATS(fc_encrypts[encrypt]);
505     if (encrypt)
506         fc_ecb_enc(in[0], in[1], out, sched);
507     else
508         fc_ecb_dec(in[0], in[1], out, sched);
509     return 0;
510 }
511
512 afs_int32
513 fc_cbc_encrypt(afs_uint32 * in, afs_uint32 * out, afs_int32 length,
514                fc_KeySchedule sched, afs_uint32 * iv, int encrypt)
515 {
516     if (encrypt)
517         fc_cbc_enc(in, out, length, sched, iv);
518     else
519         fc_cbc_dec(in, out, length, sched, iv);
520     return 0;
521 }
522
523 /* Rotate two 32 bit numbers as a 56 bit number */
524 #define ROT56R(hi, lo, n) { \
525   afs_uint32 t = lo & ((1<<n)-1); \
526   lo = (lo >> n) | ((hi & ((1<<n)-1)) << (32-n)); \
527   hi = (hi >> n) | (t << (24-n)); }
528
529 /* Rotate one 64 bit number as a 56 bit number */
530 #define ROT56R64(k, n) { \
531   k = (k >> n) | ((k & ((1<<n) - 1)) << (56-n)); }
532
533 /*
534  * Generate a key schedule from key, the least significant bit in each
535  * key byte is parity and shall be ignored. This leaves 56 significant
536  * bits in the key to scatter over the 16 key schedules. For each
537  * schedule extract the low order 32 bits and use as schedule, then
538  * rotate right by 11 bits.
539  *
540  * Note that this fc_keysched() generates a schedule in natural byte
541  * order, the Transarc function does not. Therefore it's *not*
542  * possible to mix fc_keysched, fc_ecb_encrypt and fc_cbc_encrypt
543  * from different implementations. Keep them in the same module!
544  */
545 int
546 fc_keysched(void *key_, fc_KeySchedule sched)
547 {
548     const unsigned char *key = key_;
549
550     /* Do we have 56 bit longs or even longer longs? */
551 #ifdef AFS_64BIT_ENV
552     afs_uint64 k;               /* k holds all 56 non parity bits */
553
554     /* Compress out parity bits */
555     k = (*key++) >> 1;
556     k <<= 7;
557     k |= (*key++) >> 1;
558     k <<= 7;
559     k |= (*key++) >> 1;
560     k <<= 7;
561     k |= (*key++) >> 1;
562     k <<= 7;
563     k |= (*key++) >> 1;
564     k <<= 7;
565     k |= (*key++) >> 1;
566     k <<= 7;
567     k |= (*key++) >> 1;
568     k <<= 7;
569     k |= (*key) >> 1;
570
571     /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
572     *sched++ = EFF_NTOHL((afs_uint32) k);
573     ROT56R64(k, 11);
574     *sched++ = EFF_NTOHL((afs_uint32) k);
575     ROT56R64(k, 11);
576     *sched++ = EFF_NTOHL((afs_uint32) k);
577     ROT56R64(k, 11);
578     *sched++ = EFF_NTOHL((afs_uint32) k);
579     ROT56R64(k, 11);
580
581     *sched++ = EFF_NTOHL((afs_uint32) k);
582     ROT56R64(k, 11);
583     *sched++ = EFF_NTOHL((afs_uint32) k);
584     ROT56R64(k, 11);
585     *sched++ = EFF_NTOHL((afs_uint32) k);
586     ROT56R64(k, 11);
587     *sched++ = EFF_NTOHL((afs_uint32) k);
588     ROT56R64(k, 11);
589
590     *sched++ = EFF_NTOHL((afs_uint32) k);
591     ROT56R64(k, 11);
592     *sched++ = EFF_NTOHL((afs_uint32) k);
593     ROT56R64(k, 11);
594     *sched++ = EFF_NTOHL((afs_uint32) k);
595     ROT56R64(k, 11);
596     *sched++ = EFF_NTOHL((afs_uint32) k);
597     ROT56R64(k, 11);
598
599     *sched++ = EFF_NTOHL((afs_uint32) k);
600     ROT56R64(k, 11);
601     *sched++ = EFF_NTOHL((afs_uint32) k);
602     ROT56R64(k, 11);
603     *sched++ = EFF_NTOHL((afs_uint32) k);
604     ROT56R64(k, 11);
605     *sched++ = EFF_NTOHL((afs_uint32) k);
606 #else
607     afs_uint32 hi, lo;          /* hi is upper 24 bits and lo lower 32, total 56 */
608
609     /* Compress out parity bits */
610     lo = (*key++) >> 1;
611     lo <<= 7;
612     lo |= (*key++) >> 1;
613     lo <<= 7;
614     lo |= (*key++) >> 1;
615     lo <<= 7;
616     lo |= (*key++) >> 1;
617     hi = lo >> 4;
618     lo &= 0xf;
619     lo <<= 7;
620     lo |= (*key++) >> 1;
621     lo <<= 7;
622     lo |= (*key++) >> 1;
623     lo <<= 7;
624     lo |= (*key++) >> 1;
625     lo <<= 7;
626     lo |= (*key) >> 1;
627
628     /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
629     *sched++ = EFF_NTOHL(lo);
630     ROT56R(hi, lo, 11);
631     *sched++ = EFF_NTOHL(lo);
632     ROT56R(hi, lo, 11);
633     *sched++ = EFF_NTOHL(lo);
634     ROT56R(hi, lo, 11);
635     *sched++ = EFF_NTOHL(lo);
636     ROT56R(hi, lo, 11);
637
638     *sched++ = EFF_NTOHL(lo);
639     ROT56R(hi, lo, 11);
640     *sched++ = EFF_NTOHL(lo);
641     ROT56R(hi, lo, 11);
642     *sched++ = EFF_NTOHL(lo);
643     ROT56R(hi, lo, 11);
644     *sched++ = EFF_NTOHL(lo);
645     ROT56R(hi, lo, 11);
646
647     *sched++ = EFF_NTOHL(lo);
648     ROT56R(hi, lo, 11);
649     *sched++ = EFF_NTOHL(lo);
650     ROT56R(hi, lo, 11);
651     *sched++ = EFF_NTOHL(lo);
652     ROT56R(hi, lo, 11);
653     *sched++ = EFF_NTOHL(lo);
654     ROT56R(hi, lo, 11);
655
656     *sched++ = EFF_NTOHL(lo);
657     ROT56R(hi, lo, 11);
658     *sched++ = EFF_NTOHL(lo);
659     ROT56R(hi, lo, 11);
660     *sched++ = EFF_NTOHL(lo);
661     ROT56R(hi, lo, 11);
662     *sched++ = EFF_NTOHL(lo);
663 #endif
664     INC_RXKAD_STATS(fc_key_scheds);
665     return 0;
666 }
667
668 /*
669  * Encryption/decryption of Rx packets is pretty straight forward. Run
670  * fc_cbc_encrypt over the packet fragments until len bytes have been
671  * processed. Skip the Rx packet header but not the security header.
672  */
673 afs_int32
674 rxkad_EncryptPacket(const struct rx_connection * rx_connection_not_used,
675                     const fc_KeySchedule * sched, const afs_uint32 * iv,
676                     int len, struct rx_packet * packet)
677 {
678     afs_uint32 ivec[2];
679     struct iovec *frag;
680     struct rx_securityClass *obj;
681     struct rxkad_cprivate *tp;  /* s & c have type at same offset */
682
683     obj = rx_SecurityObjectOf(rx_connection_not_used);
684     tp = (struct rxkad_cprivate *)obj->privateData;
685     ADD_RXKAD_STATS(bytesEncrypted[rxkad_TypeIndex(tp->type)],len);
686     {
687         /* What is this good for?
688          * It turns out that the security header for auth_enc is of
689          * size 8 bytes and the last 4 bytes are defined to be 0!
690          */
691         afs_uint32 *t = (afs_uint32 *) packet->wirevec[1].iov_base;
692         t[1] = 0;
693     }
694
695     memcpy(ivec, iv, sizeof(ivec));     /* Must use copy of iv */
696     for (frag = &packet->wirevec[1]; len; frag++) {
697         int iov_len = frag->iov_len;
698         afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base;
699         if (iov_len == 0)
700             return RXKADDATALEN;        /* Length mismatch */
701         if (len < iov_len)
702             iov_len = len;      /* Don't process to much data */
703         fc_cbc_enc(iov_bas, iov_bas, iov_len, sched, ivec);
704         len -= iov_len;
705     }
706     return 0;
707 }
708
709 afs_int32
710 rxkad_DecryptPacket(const struct rx_connection * rx_connection_not_used,
711                     const fc_KeySchedule * sched, const afs_uint32 * iv,
712                     int len, struct rx_packet * packet)
713 {
714     afs_uint32 ivec[2];
715     struct iovec *frag;
716     struct rx_securityClass *obj;
717     struct rxkad_cprivate *tp;  /* s & c have type at same offset */
718
719     obj = rx_SecurityObjectOf(rx_connection_not_used);
720     tp = (struct rxkad_cprivate *)obj->privateData;
721     ADD_RXKAD_STATS(bytesDecrypted[rxkad_TypeIndex(tp->type)],len);
722     memcpy(ivec, iv, sizeof(ivec));     /* Must use copy of iv */
723     for (frag = &packet->wirevec[1]; len > 0; frag++) {
724         int iov_len = frag->iov_len;
725         afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base;
726         if (iov_len == 0)
727             return RXKADDATALEN;        /* Length mismatch */
728         if (len < iov_len)
729             iov_len = len;      /* Don't process to much data */
730         fc_cbc_dec(iov_bas, iov_bas, iov_len, sched, ivec);
731         len -= iov_len;
732     }
733     return 0;
734 }
735
736 #if defined(TEST) || defined(TEST_KERNEL)
737 /*
738  * It is possible to link with the client kernel libafs.a to verify
739  * the test case. Use TEST_KERNEL to get the mangled names.
740  */
741
742 #include <stdio.h>
743 #include <string.h>
744
745 #include <time.h>
746
747 const char the_quick[] = "The quick brown fox jumps over the lazy dogs.\0\0";
748
749 const unsigned char key1[8] =
750     { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 };
751 const char ciph1[] = {
752     0x00, 0xf0, 0xe, 0x11, 0x75, 0xe6, 0x23, 0x82, 0xee, 0xac, 0x98, 0x62,
753     0x44, 0x51, 0xe4, 0x84, 0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
754     0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03, 0x23, 0xb5, 0x62, 0xd7,
755     0xc, 0xf5, 0x27, 0xd1, 0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef
756 };
757
758 const unsigned char key2[8] =
759     { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
760 const char ciph2[] = {
761     0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c, 0x01, 0x88, 0x7f, 0x3e,
762     0x31, 0x6e, 0x62, 0x9d, 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
763     0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0, 0x19, 0x89, 0x09, 0x1c,
764     0x2a, 0x8e, 0x8c, 0x94, 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f
765 };
766
767 #ifdef TEST_KERNEL
768 #define fc_keysched    _afs_QTKrFdpoFL
769 #define fc_ecb_encrypt _afs_sDLThwNLok
770 #define fc_cbc_encrypt _afs_fkyCWTvfRS
771 #define rxkad_DecryptPacket _afs_SRWEeqTXrS
772 #define rxkad_EncryptPacket _afs_bpwQbdoghO
773 #endif
774
775 int
776 rx_SlowPutInt32()
777 {
778     abort();
779 }
780
781 int
782 main()
783 {
784     afs_int32 sched[MAXROUNDS];
785     char ciph[100], clear[100], tmp[100];
786     afs_uint32 data[2];
787     afs_uint32 iv[2];
788     struct rx_packet packet;
789
790     if (sizeof(afs_int32) != 4)
791         fprintf(stderr, "error: sizeof(afs_int32) != 4\n");
792     if (sizeof(afs_uint32) != 4)
793         fprintf(stderr, "error: sizeof(afs_uint32) != 4\n");
794
795     /*
796      * Use key1 and key2 as iv */
797     fc_keysched(key1, sched);
798     memcpy(iv, key2, sizeof(iv));
799     fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
800     if (memcmp(ciph1, ciph, sizeof(ciph1)) != 0)
801         fprintf(stderr, "encrypt FAILED\n");
802     memcpy(iv, key2, sizeof(iv));
803     fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
804     if (strcmp(the_quick, clear) != 0)
805         fprintf(stderr, "crypt decrypt FAILED\n");
806
807     /*
808      * Use key2 and key1 as iv
809      */
810     fc_keysched(key2, sched);
811     memcpy(iv, key1, sizeof(iv));
812     fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
813     if (memcmp(ciph2, ciph, sizeof(ciph2)) != 0)
814         fprintf(stderr, "encrypt FAILED\n");
815     memcpy(iv, key1, sizeof(iv));
816     fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
817     if (strcmp(the_quick, clear) != 0)
818         fprintf(stderr, "crypt decrypt FAILED\n");
819
820     /*
821      * Test Encrypt- and Decrypt-Packet, use key1 and key2 as iv
822      */
823     fc_keysched(key1, sched);
824     memcpy(iv, key2, sizeof(iv));
825     strcpy(clear, the_quick);
826     packet.wirevec[1].iov_base = clear;
827     packet.wirevec[1].iov_len = sizeof(the_quick);
828     packet.wirevec[2].iov_len = 0;
829
830     /* For unknown reasons bytes 4-7 are zeroed in rxkad_EncryptPacket */
831     rxkad_EncryptPacket(tmp, sched, iv, sizeof(the_quick), &packet);
832     rxkad_DecryptPacket(tmp, sched, iv, sizeof(the_quick), &packet);
833     clear[4] ^= 'q';
834     clear[5] ^= 'u';
835     clear[6] ^= 'i';
836     clear[7] ^= 'c';
837     if (strcmp(the_quick, clear) != 0)
838         fprintf(stderr, "rxkad_EncryptPacket/rxkad_DecryptPacket FAILED\n");
839
840     {
841         struct timeval start, stop;
842         int i;
843
844         fc_keysched(key1, sched);
845         gettimeofday(&start, 0);
846         for (i = 0; i < 1000000; i++)
847             fc_keysched(key1, sched);
848         gettimeofday(&stop, 0);
849         printf("fc_keysched    = %2.2f us\n",
850                (stop.tv_sec - start.tv_sec +
851                 (stop.tv_usec - start.tv_usec) / 1e6) * 1);
852
853         fc_ecb_encrypt(data, data, sched, ENCRYPT);
854         gettimeofday(&start, 0);
855         for (i = 0; i < 1000000; i++)
856             fc_ecb_encrypt(data, data, sched, ENCRYPT);
857         gettimeofday(&stop, 0);
858         printf("fc_ecb_encrypt = %2.2f us\n",
859                (stop.tv_sec - start.tv_sec +
860                 (stop.tv_usec - start.tv_usec) / 1e6) * 1);
861
862         fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv,
863                        ENCRYPT);
864         gettimeofday(&start, 0);
865         for (i = 0; i < 100000; i++)
866             fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv,
867                            ENCRYPT);
868         gettimeofday(&stop, 0);
869         printf("fc_cbc_encrypt = %2.2f us\n",
870                (stop.tv_sec - start.tv_sec +
871                 (stop.tv_usec - start.tv_usec) / 1e6) * 10);
872
873     }
874
875     exit(0);
876 }
877 #endif /* TEST */