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