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