systm-h-header-inclusion-20060227
[openafs.git] / src / rxkad / domestic / fcrypt.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* NOTE: fc_cbc_encrypt now modifies its 5th argument, to permit chaining over
11  * scatter/gather vectors.
12  */
13
14
15 #include <afsconfig.h>
16 #ifdef KERNEL
17 #include "afs/param.h"
18 #else
19 #include <afs/param.h>
20 #endif
21
22 RCSID
23     ("$Header$");
24
25 #define DEBUG 0
26 #ifdef KERNEL
27 #ifndef UKERNEL
28 #include "afs/stds.h"
29 #if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV) 
30 #include "h/systm.h"
31 #endif
32 #include "h/types.h"
33 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_OBSD_ENV)
34 #include "netinet/in.h"
35 #endif
36 #else /* UKERNEL */
37 #include "afs/sysincludes.h"
38 #include "afs/stds.h"
39 #endif /* UKERNEL */
40 #ifdef AFS_LINUX22_ENV
41 #include <asm/byteorder.h>
42 #endif
43
44 #include "afs/longc_procs.h"
45
46 #else /* KERNEL */
47
48 #include <afs/stds.h>
49 #include <sys/types.h>
50 #ifdef AFS_NT40_ENV
51 #include <winsock2.h>
52 #else
53 #include <netinet/in.h>
54 #endif
55 #include <rx/rx.h>
56 #endif /* KERNEL */
57
58 #include "sboxes.h"
59 #include "fcrypt.h"
60 #include "rxkad.h"
61 #include <des/stats.h>
62
63 #ifdef TCRYPT
64 int ROUNDS = 16;
65 #else
66 #define ROUNDS 16
67 #endif
68
69 #define XPRT_FCRYPT
70
71 int
72 fc_keysched(struct ktc_encryptionKey *key, fc_KeySchedule schedule)
73 {
74     unsigned char *keychar = (unsigned char *)key;
75     afs_uint32 kword[2];
76
77     unsigned int temp;
78     int i;
79
80     /* first, flush the losing key parity bits. */
81     kword[0] = (*keychar++) >> 1;
82     kword[0] <<= 7;
83     kword[0] += (*keychar++) >> 1;
84     kword[0] <<= 7;
85     kword[0] += (*keychar++) >> 1;
86     kword[0] <<= 7;
87     kword[0] += (*keychar++) >> 1;
88     kword[1] = kword[0] >> 4;   /* get top 24 bits for hi word */
89     kword[0] &= 0xf;
90     kword[0] <<= 7;
91     kword[0] += (*keychar++) >> 1;
92     kword[0] <<= 7;
93     kword[0] += (*keychar++) >> 1;
94     kword[0] <<= 7;
95     kword[0] += (*keychar++) >> 1;
96     kword[0] <<= 7;
97     kword[0] += (*keychar) >> 1;
98
99     schedule[0] = kword[0];
100     for (i = 1; i < ROUNDS; i++) {
101         /* rotate right 3 */
102         temp = kword[0] & ((1 << 11) - 1);      /* get 11 lsb */
103         kword[0] =
104             (kword[0] >> 11) | ((kword[1] & ((1 << 11) - 1)) << (32 - 11));
105         kword[1] = (kword[1] >> 11) | (temp << (56 - 32 - 11));
106         schedule[i] = kword[0];
107     }
108     INC_RXKAD_STATS(fc_key_scheds);
109     return 0;
110 }
111
112 /* IN int encrypt; * 0 ==> decrypt, else encrypt */
113 afs_int32
114 fc_ecb_encrypt(void * clear, void * cipher,
115                fc_KeySchedule schedule, int encrypt)
116 {
117     afs_uint32 L, R;
118     volatile afs_uint32 S, P;
119     volatile unsigned char *Pchar = (unsigned char *)&P;
120     volatile unsigned char *Schar = (unsigned char *)&S;
121     int i;
122
123 #if defined(vax) || (defined(mips) && defined(MIPSEL)) || defined(AFSLITTLE_ENDIAN)
124 #define Byte0 3
125 #define Byte1 2
126 #define Byte2 1
127 #define Byte3 0
128 #else
129 #define Byte0 0
130 #define Byte1 1
131 #define Byte2 2
132 #define Byte3 3
133 #endif
134
135 #if 0
136     memcpy(&L, clear, sizeof(afs_int32));
137     memcpy(&R, clear + 1, sizeof(afs_int32));
138 #else
139     L = ntohl(*((afs_uint32 *)clear));
140     R = ntohl(*((afs_uint32 *)clear + 1));
141 #endif
142
143     if (encrypt) {
144         INC_RXKAD_STATS(fc_encrypts[ENCRYPT]);
145         for (i = 0; i < (ROUNDS / 2); i++) {
146             S = *schedule++ ^ R;        /* xor R with key bits from schedule */
147             Pchar[Byte2] = sbox0[Schar[Byte0]]; /* do 8-bit S Box subst. */
148             Pchar[Byte3] = sbox1[Schar[Byte1]]; /* and permute the result */
149             Pchar[Byte1] = sbox2[Schar[Byte2]];
150             Pchar[Byte0] = sbox3[Schar[Byte3]];
151             P = (P >> 5) | ((P & ((1 << 5) - 1)) << (32 - 5));  /* right rot 5 bits */
152             L ^= P;             /* we're done with L, so save there */
153             S = *schedule++ ^ L;        /* this time xor with L */
154             Pchar[Byte2] = sbox0[Schar[Byte0]];
155             Pchar[Byte3] = sbox1[Schar[Byte1]];
156             Pchar[Byte1] = sbox2[Schar[Byte2]];
157             Pchar[Byte0] = sbox3[Schar[Byte3]];
158             P = (P >> 5) | ((P & ((1 << 5) - 1)) << (32 - 5));  /* right rot 5 bits */
159             R ^= P;
160         }
161     } else {
162         INC_RXKAD_STATS(fc_encrypts[DECRYPT]);
163         schedule = &schedule[ROUNDS - 1];       /* start at end of key schedule */
164         for (i = 0; i < (ROUNDS / 2); i++) {
165             S = *schedule-- ^ L;        /* xor R with key bits from schedule */
166             Pchar[Byte2] = sbox0[Schar[Byte0]]; /* do 8-bit S Box subst. and */
167             Pchar[Byte3] = sbox1[Schar[Byte1]]; /* permute the result */
168             Pchar[Byte1] = sbox2[Schar[Byte2]];
169             Pchar[Byte0] = sbox3[Schar[Byte3]];
170             P = (P >> 5) | ((P & ((1 << 5) - 1)) << (32 - 5));  /* right rot 5 bits */
171             R ^= P;             /* we're done with L, so save there */
172             S = *schedule-- ^ R;        /* this time xor with L */
173             Pchar[Byte2] = sbox0[Schar[Byte0]];
174             Pchar[Byte3] = sbox1[Schar[Byte1]];
175             Pchar[Byte1] = sbox2[Schar[Byte2]];
176             Pchar[Byte0] = sbox3[Schar[Byte3]];
177             P = (P >> 5) | ((P & ((1 << 5) - 1)) << (32 - 5));  /* right rot 5 bits */
178             L ^= P;
179         }
180     }
181 #if 0
182     memcpy(cipher, &L, sizeof(afs_int32));
183     memcpy(cipher + 1, &R, sizeof(afs_int32));
184 #else
185     *((afs_int32 *)cipher) = htonl(L);
186     *((afs_int32 *)cipher + 1) = htonl(R);
187 #endif
188     return 0;
189 }
190
191 /* Crypting can be done in segments by recycling xor.  All but the final segment must
192  * be multiples of 8 bytes.
193  * NOTE: fc_cbc_encrypt now modifies its 5th argument, to permit chaining over
194  * scatter/gather vectors.
195  */
196 /*
197   afs_int32 length; * in bytes *
198   int encrypt; * 0 ==> decrypt, else encrypt *
199   fc_KeySchedule key; * precomputed key schedule *
200   afs_uint32 *xor; * 8 bytes of initialization vector *
201 */
202 afs_int32
203 fc_cbc_encrypt(void *input, void *output, afs_int32 length,
204                fc_KeySchedule key, afs_uint32 * xor, int encrypt)
205 {
206     afs_uint32 i, j;
207     afs_uint32 t_input[2];
208     afs_uint32 t_output[2];
209     unsigned char *t_in_p = (unsigned char *)t_input;
210
211     if (encrypt) {
212         for (i = 0; length > 0; i++, length -= 8) {
213             /* get input */
214             memcpy(t_input, input, sizeof(t_input));
215             input=((char *)input) + sizeof(t_input);
216
217             /* zero pad */
218             for (j = length; j <= 7; j++)
219                 *(t_in_p + j) = 0;
220
221             /* do the xor for cbc into the temp */
222             xor[0] ^= t_input[0];
223             xor[1] ^= t_input[1];
224             /* encrypt */
225             fc_ecb_encrypt(xor, t_output, key, encrypt);
226
227             /* copy temp output and save it for cbc */
228             memcpy(output, t_output, sizeof(t_output));
229             output=(char *)output + sizeof(t_output);
230
231             /* calculate xor value for next round from plain & cipher text */
232             xor[0] = t_input[0] ^ t_output[0];
233             xor[1] = t_input[1] ^ t_output[1];
234
235
236         }
237         t_output[0] = 0;
238         t_output[1] = 0;
239     } else {
240         /* decrypt */
241         for (i = 0; length > 0; i++, length -= 8) {
242             /* get input */
243             memcpy(t_input, input, sizeof(t_input));
244             input=((char *)input) + sizeof(t_input);
245
246             /* no padding for decrypt */
247             fc_ecb_encrypt(t_input, t_output, key, encrypt);
248
249             /* do the xor for cbc into the output */
250             t_output[0] ^= xor[0];
251             t_output[1] ^= xor[1];
252
253             /* copy temp output */
254             memcpy(output, t_output, sizeof(t_output));
255             output=((char *)output) + sizeof(t_output);
256
257             /* calculate xor value for next round from plain & cipher text */
258             xor[0] = t_input[0] ^ t_output[0];
259             xor[1] = t_input[1] ^ t_output[1];
260         }
261     }
262     return 0;
263 }