2 * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
33 #include <afsconfig.h>
35 #include "afs/param.h"
37 #include <afs/param.h>
47 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_OBSD_ENV)
48 #include "netinet/in.h"
51 #include "afs/sysincludes.h"
54 #ifdef AFS_LINUX22_ENV
55 #include <asm/byteorder.h>
58 #include "afs/longc_procs.h"
63 #include <sys/types.h>
67 #include <netinet/in.h>
75 #include "private_data.h"
77 #undef WORDS_BIGENDIAN
79 #define WORDS_BIGENDIAN 1
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.
87 #define UNROLL_LOOPS 1
89 * Inline assembler gives a boost only to fc_keysched.
90 * On the pentium expect ca 28%.
92 /*#define GNU_ASM 1 (now autoconfed) */
94 #if !defined(inline) && !defined(__GNUC__)
99 * There is usually no memcpy in kernels but gcc will inline all
100 * calls to memcpy in this code anyway.
102 #if defined(KERNEL) && !defined(__GNUC__)
103 #define memcpy(to, from, n) bcopy((from), (to), (n))
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))
113 #define NTOH(x) bswap32(x)
117 * Try to use a good function for ntohl-ing.
119 * The choice is done by autoconf setting EFF_NTOHL to one of:
127 #define EFF_NTOHL(x) ntohl(x)
130 #if defined(__GNUC__) && (defined(i386) || defined(__i386__))
131 static inline afs_uint32
134 asm("bswap %0" : "=r" (x) : "0" (x));
141 * Sboxes for Feistel network derived from
142 * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
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)};
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)};
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)};
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)};
258 * This is a 16 round Feistel network with permutation F_ENCRYPT
261 #define F_ENCRYPT(R, L, sched) { \
262 union lc4 { afs_uint32 l; unsigned char c[4]; } un; \
264 L ^= sbox0[un.c[0]] ^ sbox1[un.c[1]] ^ sbox2[un.c[2]] ^ sbox3[un.c[3]]; }
266 #ifndef WORDS_BIGENDIAN
267 /* BEWARE: this code is endian dependent.
268 * This should really be inline assembler on the x86.
271 #define FF(y, shiftN) (((y) >> shiftN) & 0xFF)
272 #define F_ENCRYPT(R, L, sched) { \
275 L ^= sbox0[FF(un, 0)] ^ sbox1[FF(un, 8)] ^ sbox2[FF(un, 16)] ^ sbox3[FF(un, 24)];}
280 fc_ecb_enc(afs_uint32 l,
283 const afs_int32 sched[MAXROUNDS])
285 #if !defined(UNROLL_LOOPS)
288 for (i = 0; i < (MAXROUNDS/4); i++)
290 F_ENCRYPT(r, l, *sched++);
291 F_ENCRYPT(l, r, *sched++);
292 F_ENCRYPT(r, l, *sched++);
293 F_ENCRYPT(l, r, *sched++);
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 */
321 fc_ecb_dec(afs_uint32 l,
324 const afs_int32 sched[MAXROUNDS])
326 sched = &sched[MAXROUNDS-1];
328 #if !defined(UNROLL_LOOPS)
331 for (i = 0; i < (MAXROUNDS/4); i++)
333 F_ENCRYPT(l, r, *sched--);
334 F_ENCRYPT(r, l, *sched--);
335 F_ENCRYPT(l, r, *sched--);
336 F_ENCRYPT(r, l, *sched--);
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 */
364 fc_cbc_enc(const afs_uint32 *in,
367 const afs_int32 sched[MAXROUNDS],
370 afs_int32 xor0 = iv[0], xor1 = iv[1];
372 for (; length > 0; length -= 8)
375 /* If length < 8 we read to much, usally ok */
378 fc_ecb_enc(xor0, xor1, b8, sched);
379 xor0 = in[0] ^ b8[0];
380 xor1 = in[1] ^ b8[1];
382 /* Out is always a multiple of 8 */
393 fc_cbc_dec(const afs_uint32 *in,
396 const afs_int32 sched[MAXROUNDS],
399 afs_int32 xor0 = iv[0], xor1 = iv[1];
401 for (; length > 0; length -= 8)
404 /* In is always a multiple of 8 */
405 fc_ecb_dec(in[0], in[1], b8, sched);
408 xor0 = in[0] ^ b8[0];
409 xor1 = in[1] ^ b8[1];
415 memcpy(out, b8, length); /* Don't write to much when length < 8 */
417 /* If length < 8 we write to much, this is not always ok */
428 fc_ecb_encrypt(afs_uint32 *in, afs_uint32 *out,
429 fc_KeySchedule sched,
433 rxkad_stats.fc_encrypts[encrypt]++;
436 fc_ecb_enc(in[0], in[1], out, sched);
438 fc_ecb_dec(in[0], in[1], out, sched);
443 fc_cbc_encrypt(afs_uint32 *in, afs_uint32 *out,
445 fc_KeySchedule sched,
450 fc_cbc_enc(in, out, length, sched, iv);
452 fc_cbc_dec(in, out, length, sched, iv);
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)); }
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)); }
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.
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!
479 fc_keysched(void *key_,
480 fc_KeySchedule sched)
482 const unsigned char *key = key_;
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 */
488 /* Compress out parity bits */
505 /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
506 *sched++ = EFF_NTOHL((afs_uint32)k);
508 *sched++ = EFF_NTOHL((afs_uint32)k);
510 *sched++ = EFF_NTOHL((afs_uint32)k);
512 *sched++ = EFF_NTOHL((afs_uint32)k);
515 *sched++ = EFF_NTOHL((afs_uint32)k);
517 *sched++ = EFF_NTOHL((afs_uint32)k);
519 *sched++ = EFF_NTOHL((afs_uint32)k);
521 *sched++ = EFF_NTOHL((afs_uint32)k);
524 *sched++ = EFF_NTOHL((afs_uint32)k);
526 *sched++ = EFF_NTOHL((afs_uint32)k);
528 *sched++ = EFF_NTOHL((afs_uint32)k);
530 *sched++ = EFF_NTOHL((afs_uint32)k);
533 *sched++ = EFF_NTOHL((afs_uint32)k);
535 *sched++ = EFF_NTOHL((afs_uint32)k);
537 *sched++ = EFF_NTOHL((afs_uint32)k);
539 *sched++ = EFF_NTOHL((afs_uint32)k);
541 afs_uint32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */
543 /* Compress out parity bits */
562 /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
563 *sched++ = EFF_NTOHL(lo);
565 *sched++ = EFF_NTOHL(lo);
567 *sched++ = EFF_NTOHL(lo);
569 *sched++ = EFF_NTOHL(lo);
572 *sched++ = EFF_NTOHL(lo);
574 *sched++ = EFF_NTOHL(lo);
576 *sched++ = EFF_NTOHL(lo);
578 *sched++ = EFF_NTOHL(lo);
581 *sched++ = EFF_NTOHL(lo);
583 *sched++ = EFF_NTOHL(lo);
585 *sched++ = EFF_NTOHL(lo);
587 *sched++ = EFF_NTOHL(lo);
590 *sched++ = EFF_NTOHL(lo);
592 *sched++ = EFF_NTOHL(lo);
594 *sched++ = EFF_NTOHL(lo);
596 *sched++ = EFF_NTOHL(lo);
599 rxkad_stats.fc_key_scheds++;
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.
610 rxkad_EncryptPacket(const struct rx_connection *rx_connection_not_used,
611 const fc_KeySchedule *sched,
612 const afs_uint32 *iv,
614 struct rx_packet *packet)
618 struct rx_securityClass *obj;
619 struct rxkad_cprivate *tp; /* s & c have type at same offset */
621 obj = rx_SecurityObjectOf(rx_connection_not_used);
622 tp = (struct rxkad_cprivate *)obj->privateData;
624 rxkad_stats.bytesEncrypted[rxkad_TypeIndex(tp->type)] += len;
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!
632 afs_uint32 *t = (afs_uint32 *)packet->wirevec[1].iov_base;
636 memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */
637 for (frag = &packet->wirevec[1]; len; frag++)
639 int iov_len = frag->iov_len;
640 afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base;
642 return RXKADDATALEN; /* Length mismatch */
644 iov_len = len; /* Don't process to much data */
645 fc_cbc_enc(iov_bas, iov_bas, iov_len, sched, ivec);
652 rxkad_DecryptPacket(const struct rx_connection *rx_connection_not_used,
653 const fc_KeySchedule *sched,
654 const afs_uint32 *iv,
656 struct rx_packet *packet)
660 struct rx_securityClass *obj;
661 struct rxkad_cprivate *tp; /* s & c have type at same offset */
663 obj = rx_SecurityObjectOf(rx_connection_not_used);
664 tp = (struct rxkad_cprivate *)obj->privateData;
666 rxkad_stats.bytesDecrypted[rxkad_TypeIndex(tp->type)] += len;
669 memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */
670 for (frag = &packet->wirevec[1]; len > 0; frag++)
672 int iov_len = frag->iov_len;
673 afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base;
675 return RXKADDATALEN; /* Length mismatch */
677 iov_len = len; /* Don't process to much data */
678 fc_cbc_dec(iov_bas, iov_bas, iov_len, sched, ivec);
684 #if defined(TEST) || defined(TEST_KERNEL)
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.
695 const char the_quick[] = "The quick brown fox jumps over the lazy dogs.\0\0";
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 };
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 };
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
719 int rx_SlowPutInt32() { abort(); }
724 afs_int32 sched[MAXROUNDS];
725 char ciph[100], clear[100], tmp[100];
728 struct rx_packet packet;
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");
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");
748 * Use key2 and key1 as iv
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");
761 * Test Encrypt- and Decrypt-Packet, use key1 and key2 as iv
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;
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);
777 if (strcmp(the_quick, clear) != 0)
778 fprintf(stderr, "rxkad_EncryptPacket/rxkad_DecryptPacket FAILED\n");
781 struct timeval start, stop;
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);
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);
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);