2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* NOTE: fc_cbc_encrypt now modifies its 5th argument, to permit chaining over
11 * scatter/gather vectors.
15 #include <afsconfig.h>
17 #include "afs/param.h"
19 #include <afs/param.h>
29 #if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV)
33 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_OBSD_ENV)
34 #include "netinet/in.h"
37 #include "afs/sysincludes.h"
40 #ifdef AFS_LINUX22_ENV
41 #include <asm/byteorder.h>
44 #include "afs/longc_procs.h"
49 #include <sys/types.h>
53 #include <netinet/in.h>
61 #include <des/stats.h>
72 fc_keysched(struct ktc_encryptionKey *key, fc_KeySchedule schedule)
74 unsigned char *keychar = (unsigned char *)key;
80 /* first, flush the losing key parity bits. */
81 kword[0] = (*keychar++) >> 1;
83 kword[0] += (*keychar++) >> 1;
85 kword[0] += (*keychar++) >> 1;
87 kword[0] += (*keychar++) >> 1;
88 kword[1] = kword[0] >> 4; /* get top 24 bits for hi word */
91 kword[0] += (*keychar++) >> 1;
93 kword[0] += (*keychar++) >> 1;
95 kword[0] += (*keychar++) >> 1;
97 kword[0] += (*keychar) >> 1;
99 schedule[0] = kword[0];
100 for (i = 1; i < ROUNDS; i++) {
102 temp = kword[0] & ((1 << 11) - 1); /* get 11 lsb */
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];
108 INC_RXKAD_STATS(fc_key_scheds);
112 /* IN int encrypt; * 0 ==> decrypt, else encrypt */
114 fc_ecb_encrypt(void * clear, void * cipher,
115 fc_KeySchedule schedule, int encrypt)
118 volatile afs_uint32 S, P;
119 volatile unsigned char *Pchar = (unsigned char *)&P;
120 volatile unsigned char *Schar = (unsigned char *)&S;
123 #ifndef WORDS_BIGENDIAN
136 memcpy(&L, clear, sizeof(afs_int32));
137 memcpy(&R, clear + 1, sizeof(afs_int32));
139 L = ntohl(*((afs_uint32 *)clear));
140 R = ntohl(*((afs_uint32 *)clear + 1));
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 */
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 */
182 memcpy(cipher, &L, sizeof(afs_int32));
183 memcpy(cipher + 1, &R, sizeof(afs_int32));
185 *((afs_int32 *)cipher) = htonl(L);
186 *((afs_int32 *)cipher + 1) = htonl(R);
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.
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 *
203 fc_cbc_encrypt(void *input, void *output, afs_int32 length,
204 fc_KeySchedule key, afs_uint32 * xor, int encrypt)
207 afs_uint32 t_input[2];
208 afs_uint32 t_output[2];
209 unsigned char *t_in_p = (unsigned char *)t_input;
212 for (i = 0; length > 0; i++, length -= 8) {
214 memcpy(t_input, input, sizeof(t_input));
215 input=((char *)input) + sizeof(t_input);
218 for (j = length; j <= 7; j++)
221 /* do the xor for cbc into the temp */
222 xor[0] ^= t_input[0];
223 xor[1] ^= t_input[1];
225 fc_ecb_encrypt(xor, t_output, key, encrypt);
227 /* copy temp output and save it for cbc */
228 memcpy(output, t_output, sizeof(t_output));
229 output=(char *)output + sizeof(t_output);
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];
241 for (i = 0; length > 0; i++, length -= 8) {
243 memcpy(t_input, input, sizeof(t_input));
244 input=((char *)input) + sizeof(t_input);
246 /* no padding for decrypt */
247 fc_ecb_encrypt(t_input, t_output, key, encrypt);
249 /* do the xor for cbc into the output */
250 t_output[0] ^= xor[0];
251 t_output[1] ^= xor[1];
253 /* copy temp output */
254 memcpy(output, t_output, sizeof(t_output));
255 output=((char *)output) + sizeof(t_output);
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];