2 * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
5 * For copying and distribution information, please see the file
8 * These routines perform encryption and decryption using the DES
9 * private key algorithm, or else a subset of it-- fewer inner loops.
10 * (AUTH_DES_ITER defaults to 16, may be less.)
12 * Under U.S. law, this software may not be exported outside the US
13 * without license from the U.S. Commerce department.
15 * The key schedule is passed as an arg, as well as the cleartext or
18 * All registers labeled imply Vax using the Ultrix or 4.2bsd
22 * NOTE: bit and byte numbering:
23 * DES algorithm is defined in terms of bits of L
24 * followed by bits of R.
29 * Always work in register pairs, FROM L1,R1 TO L2,R2 to make
32 * originally written by Steve Miller, MIT Project Athena
34 #include <mit-cpyright.h>
36 #include <afsconfig.h>
37 #include <afs/param.h>
42 #ifdef AFS_PTHREAD_ENV
44 #endif /* AFS_PTHREAD_ENV */
46 #include "des_internal.h"
56 #define DBG_PRINT(s) if (des_debug & 2) \
57 des_debug_print(s,i,L1&0xffff,(L1>>16)&0xffff, \
58 R1&0xffff,(R1>>16)&0xffff)
64 extern int des_cblock_print_file ();
65 extern int des_debug_print ();
66 extern int swap_long_bytes_bit_number(int);
68 #ifdef AFS_PTHREAD_ENV
69 pthread_mutex_t rxkad_stats_mutex;
70 #endif /* AFS_PTHREAD_ENV */
73 des_ecb_encrypt(clear, cipher, schedule, encrypt)
76 int encrypt; /* 0 ==> decrypt, else encrypt */
77 register des_key_schedule schedule; /* r11 */
80 /* better pass 8 bytes, length not checked here */
82 register afs_uint32 R1, L1; /* R1 = r10, L1 = r9 */
83 register afs_uint32 R2, L2; /* R2 = r8, L2 = r7 */
85 /* one more registers left on VAX, see below P_temp_p */
87 sbox_in_16_a S_in_16_a;
88 sbox_in_16_b S_in_16_b;
89 sbox_in_16_c S_in_16_c;
90 unsigned int *S_in_a_16_p = (unsigned int *) &S_in_16_a;
91 unsigned int *S_in_b_16_p = (unsigned int *) &S_in_16_b;
92 unsigned int *S_in_c_16_p = (unsigned int *) &S_in_16_c;
96 dunno how to do this machine type, you lose;
100 register unsigned char *P_temp_p = (unsigned char *) & P_temp;
103 afs_uint32 *S_out_p = (afs_uint32 *) &S_out;
105 afs_uint32 R_save, L_save;
107 afs_uint32 dbg_tmp[2];
110 if (encrypt) rxkad_stats.des_encrypts[DES_ENCRYPT]++;
111 else rxkad_stats.des_encrypts[DES_DECRYPT]++;
115 * Use L1,R1 and L2,R2 as two sets of "64-bit" registers always
116 * work from L1,R1 input to L2,R2 output; initialize the cleartext
122 * If the alignment is wrong, the programmer really screwed up --
123 * we aren't even getting the right data type. His problem. Keep
124 * this code for debugging.
126 /* Make sure schedule is ok */
127 if ((afs_int32) schedule & 3) {
128 fprintf(stderr,"des.c schedule arg pointer not aligned\n");
132 if ((afs_int32) clear & 3) {
133 memcpy((char *)&L_save, (char *)clear++, sizeof(L_save));
134 memcpy((char *)&R_save, (char *)clear, sizeof(R_save));
141 if (clear) L1 = *clear++;
143 if (clear) R1 = *clear;
149 printf("All values printed from low byte (bit 0)");
150 printf(" --> high byte (bit 63)\n");
154 printf("iter = %2d before IP\n\t\tL1 R1 = ",i);
155 des_cblock_print_file (dbg_tmp, stdout);
158 DBG_PRINT("before IP");
163 /* all the Initial Permutation code is in the include file */
165 /* reset input to L1,R1 */
169 /* iterate through the inner loop */
170 for (i = 0; i <= (AUTH_DES_ITER-1); i++) {
176 printf("iter = %2d start loop\n\t\tL1 R1 = ",i);
177 des_cblock_print_file (dbg_tmp, stdout);
178 DBG_PRINT("start loop");
187 /* apply the E permutation from R1 to L2, R2 */
191 #else /* Bill's fast E */
196 L2 |= (R1 <<3) & 07700;
197 L2 |= (R1 <<5) & 0770000;
198 L2 |= (R1 <<7) & 077000000;
199 L2 |= (R1 <<9) & 07700000000;
200 L2 |= (R1 <<11) & 030000000000;
202 /* now from right to right */
204 R2 = ((R1 >> 17) & 0176000);
205 if (R1 & (1<<0)) R2 |= 1<<15;
207 R2 |= ((R1 >> 21) & 017);
208 R2 |= ((R1 >> 19) & 01760);
213 asm(" rotl $1,r10,r7");
215 L2 |= (R1 <<3) & 07700;
216 L2 |= (R1 <<5) & 0770000;
217 L2 |= (R1 <<7) & 077000000;
218 L2 |= (R1 <<9) & 07700000000;
219 L2 |= (R1 <<11) & 030000000000;
221 asm(" rotl $-17,r10,r8");
223 asm(" rotl $-21,r10,r0");
224 asm(" bicl2 $-16,r0");
226 asm(" rotl $-19,r10,r0");
227 asm(" bicl2 $-1009,r0");
232 /* reset input to L1,R1 */
240 DBG_PRINT("after e");
241 printf("iter = %2d after e\n\t\tL1 R1 = ",i);
242 des_cblock_print_file (dbg_tmp, stdout);
248 * XOR with the key schedule, "schedule"
250 * If this is an encryption operation, use schedule[i],
251 * otherwise use schedule [AUTH_DES_ITER-i-1]
253 * First XOR left half.
256 L1 ^= *(((afs_uint32 *) &schedule[i] )+0);
258 R1 ^= *(((afs_uint32 *) &schedule[i] )+1);
261 L1 ^= *(((afs_uint32 *) &schedule[AUTH_DES_ITER-i-1] )+0);
263 R1 ^= *(((afs_uint32 *) &schedule[AUTH_DES_ITER-i-1] )+1);
266 /* dont have to reset input to L1, R1 */
272 DBG_PRINT("after xor");
273 printf("iter = %2d after xor\n\t\tL1 R1 =",i);
274 des_cblock_print_file (dbg_tmp, stdout);
279 /* apply the S selection from L1, R1 to R2 */
285 /* S operations , cant use registers for bit field stuff */
286 /* from S_in to S_out */
289 *S_in_a_16_p = L1&0xffff;
290 *S_in_b_16_p = (L1>>16)&0xffff;
291 *S_in_c_16_p = R1&0xffff;
292 (*(afs_uint32 *) &S_out) =
293 (unsigned) S_adj[0][S_in_16_a.b0];
294 S_out.b1 = (unsigned) S_adj[1][S_in_16_a.b1];
295 /* b2 spans two words */
296 S_out.b2 = (unsigned)
297 S_adj[2][(unsigned) S_in_16_a.b2
298 + (((unsigned) S_in_16_b.b2) << 4)];
299 S_out.b3 = (unsigned) S_adj[3][S_in_16_b.b3];
300 S_out.b4 = (unsigned) S_adj[4][S_in_16_b.b4];
301 /* b5 spans both parts */
302 S_out.b5 = (unsigned)
303 S_adj[5][(unsigned) S_in_16_b.b5
304 + (((unsigned) S_in_16_c.b5) << 2)];
305 S_out.b6 = (unsigned) S_adj[6][S_in_16_c.b6];
306 S_out.b7 = (unsigned) S_adj[7][S_in_16_c.b7];
309 /* is a 32 bit sys */
311 R2 = (unsigned) S_adj[0][L1 & 077];
312 L2 = (unsigned) S_adj[1][(L1 >> 6) & 077];
314 L2 = (unsigned) S_adj[2][(L1 >> 12) & 077];
316 L2 = (unsigned) S_adj[3][(L1 >> 18) & 077];
318 L2 = (unsigned) S_adj[4][(L1 >> 24) & 077];
320 /* b5 spans both parts */
322 S_adj[5][(unsigned) ((L1 >>30) & 03) + ((R1 & 017) << 2)];
324 L2 = (unsigned) S_adj[6][(R1 >> 4) & 077];
326 L2 = (unsigned) S_adj[7][(R1 >> 10) & 077];
328 /* reset input to L1, R1 */
331 * this is the c code produced above, with
332 * extzv replaced by rotl
334 asm("bicl3 $-64,r9,r0");
335 asm("movzbl _S_adj[r0],r8");
336 asm("rotl $-6,r9,r0");
337 asm("bicl2 $-64,r0");
338 asm("movzbl _S_adj+64[r0],r7");
339 asm("ashl $4,r7,r0");
341 asm("rotl $-12,r9,r0");
342 asm("bicl2 $-64,r0");
343 asm("movzbl _S_adj+128[r0],r7");
344 asm("ashl $8,r7,r0");
346 asm("rotl $-18,r9,r0");
347 asm("bicl2 $-64,r0");
348 asm("movzbl _S_adj+192[r0],r7");
349 asm("ashl $12,r7,r0");
351 asm("rotl $-24,r9,r0");
352 asm("bicl2 $-64,r0");
353 asm("movzbl _S_adj+256[r0],r7");
354 asm("ashl $16,r7,r0");
356 asm("rotl $-30,r9,r0");
358 asm("bicl3 $-16,r10,r1");
359 asm("ashl $2,r1,r1");
361 asm("movzbl _S_adj+320[r0],r7");
362 asm("ashl $20,r7,r0");
364 asm("rotl $-4,r10,r0");
365 asm("bicl2 $-64,r0");
366 asm("movzbl _S_adj+384[r0],r7");
367 asm("ashl $24,r7,r0");
369 asm("rotl $-10,r10,r0");
370 asm("bicl2 $-64,r0");
371 asm("movzbl _S_adj+448[r0],r7");
372 asm("ashl $28,r7,r0");
383 DBG_PRINT("after s");
384 printf("iter = %2d after s\n\t\tL1 R1 = ",i);
385 des_cblock_print_file (dbg_tmp, stdout);
390 /* and then the p permutation from R1 into R2 */
392 /* reset the input to L1, R1 */
399 DBG_PRINT("after p");
400 printf("iter = %2d after p\n\t\tL1 R1 = ",i);
401 des_cblock_print_file (dbg_tmp, stdout);
405 /* R1 is the output value from the f() */
406 /* move R[iter] to L[iter+1] */
411 /* reset the input */
414 /* flip left and right before final permutation */
417 /* reset the input */
425 DBG_PRINT("before FP");
426 printf("iter = %2d before FP\n\t\tL1 R1 = ",i);
427 des_cblock_print_file (dbg_tmp, stdout);
433 /* do the final permutation from L1R1 to L2R2 */
434 /* all the fp code is in the include file */
437 /* copy the output to the ciphertext string;
438 * can be same as cleartext
442 if ((afs_int32) cipher & 3) {
443 L_save = L2; /* cant bcopy a reg */
445 memcpy((char *)cipher++, (char *)&L_save, sizeof(L_save));
446 memcpy((char *)cipher, (char *)&R_save, sizeof(R_save));
462 printf("iter = %2d done\n\t\tL1 R1 = ",i);
463 des_cblock_print_file (dbg_tmp, stdout);
467 /* that's it, no errors can be returned */