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