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>
44 #ifdef AFS_PTHREAD_ENV
46 #endif /* AFS_PTHREAD_ENV */
48 #include "des_internal.h"
54 #include "des_prototypes.h"
59 #define DBG_PRINT(s) if (des_debug & 2) \
60 des_debug_print(s,i,L1&0xffff,(L1>>16)&0xffff, \
61 R1&0xffff,(R1>>16)&0xffff)
66 /* encrypt == 0 ==> decrypt, else encrypt */
69 des_ecb_encrypt(void * clear, void * cipher,
70 register des_key_schedule schedule, int encrypt)
72 /* better pass 8 bytes, length not checked here */
74 register afs_uint32 R1 = 0;
75 register afs_uint32 L1 = 0; /* R1 = r10, L1 = r9 */
76 register afs_uint32 R2 = 0, L2 = 0; /* R2 = r8, L2 = r7 */
78 /* one more registers left on VAX, see below P_temp_p */
80 sbox_in_16_a S_in_16_a;
81 sbox_in_16_b S_in_16_b;
82 sbox_in_16_c S_in_16_c;
83 unsigned int *S_in_a_16_p = (unsigned int *)&S_in_16_a;
84 unsigned int *S_in_b_16_p = (unsigned int *)&S_in_16_b;
85 unsigned int *S_in_c_16_p = (unsigned int *)&S_in_16_c;
89 #error dunno how to do this machine type, you lose;
92 volatile afs_uint32 P_temp;
93 volatile unsigned char *P_temp_p = (unsigned char *)&P_temp;
96 afs_uint32 *S_out_p = (afs_uint32 *) & S_out;
98 afs_uint32 R_save, L_save;
100 afs_uint32 dbg_tmp[2];
103 * Use L1,R1 and L2,R2 as two sets of "64-bit" registers always
104 * work from L1,R1 input to L2,R2 output; initialize the cleartext
110 * If the alignment is wrong, the programmer really screwed up --
111 * we aren't even getting the right data type. His problem. Keep
112 * this code for debugging.
114 /* Make sure schedule is ok */
115 if ((afs_int32) schedule & 3) {
116 fprintf(stderr, "des.c schedule arg pointer not aligned\n");
120 if (afs_pointer_to_int(clear) & 3) {
121 memcpy((char *)(&L_save), (char *)clear, sizeof(L_save));
122 clear=((afs_uint32*)clear)+1;
123 memcpy((char *)(&R_save), (char *)clear, sizeof(R_save));
130 L1 = *((afs_uint32 *)clear);
131 clear=((afs_uint32*)clear)+1;
135 R1 = *((afs_uint32 *)clear);
142 printf("All values printed from low byte (bit 0)");
143 printf(" --> high byte (bit 63)\n");
147 printf("iter = %2d before IP\n\t\tL1 R1 = ", i);
148 des_cblock_print_file(dbg_tmp, stdout);
151 DBG_PRINT("before IP");
156 /* all the Initial Permutation code is in the include file */
158 /* reset input to L1,R1 */
162 /* iterate through the inner loop */
163 for (i = 0; i <= (AUTH_DES_ITER - 1); i++) {
169 printf("iter = %2d start loop\n\t\tL1 R1 = ", i);
170 des_cblock_print_file(dbg_tmp, stdout);
171 DBG_PRINT("start loop");
179 /* apply the E permutation from R1 to L2, R2 */
183 #else /* Bill's fast E */
188 L2 |= (R1 << 3) & 07700;
189 L2 |= (R1 << 5) & 0770000;
190 L2 |= (R1 << 7) & 077000000;
191 L2 |= (R1 << 9) & 07700000000;
192 L2 |= (R1 << 11) & 030000000000;
194 /* now from right to right */
196 R2 = ((R1 >> 17) & 0176000);
200 R2 |= ((R1 >> 21) & 017);
201 R2 |= ((R1 >> 19) & 01760);
206 asm(" rotl $1,r10,r7");
208 L2 |= (R1 << 3) & 07700;
209 L2 |= (R1 << 5) & 0770000;
210 L2 |= (R1 << 7) & 077000000;
211 L2 |= (R1 << 9) & 07700000000;
212 L2 |= (R1 << 11) & 030000000000;
214 asm(" rotl $-17,r10,r8");
216 asm(" rotl $-21,r10,r0");
217 asm(" bicl2 $-16,r0");
219 asm(" rotl $-19,r10,r0");
220 asm(" bicl2 $-1009,r0");
225 /* reset input to L1,R1 */
233 DBG_PRINT("after e");
234 printf("iter = %2d after e\n\t\tL1 R1 = ", i);
235 des_cblock_print_file(dbg_tmp, stdout);
241 * XOR with the key schedule, "schedule"
243 * If this is an encryption operation, use schedule[i],
244 * otherwise use schedule [AUTH_DES_ITER-i-1]
246 * First XOR left half.
249 L1 ^= *(((afs_uint32 *) & schedule[i]) + 0);
251 R1 ^= *(((afs_uint32 *) & schedule[i]) + 1);
253 L1 ^= *(((afs_uint32 *) & schedule[AUTH_DES_ITER - i - 1]) + 0);
255 R1 ^= *(((afs_uint32 *) & schedule[AUTH_DES_ITER - i - 1]) + 1);
258 /* dont have to reset input to L1, R1 */
264 DBG_PRINT("after xor");
265 printf("iter = %2d after xor\n\t\tL1 R1 =", i);
266 des_cblock_print_file(dbg_tmp, stdout);
271 /* apply the S selection from L1, R1 to R2 */
277 /* S operations , cant use registers for bit field stuff */
278 /* from S_in to S_out */
281 *S_in_a_16_p = L1 & 0xffff;
282 *S_in_b_16_p = (L1 >> 16) & 0xffff;
283 *S_in_c_16_p = R1 & 0xffff;
284 (*(afs_uint32 *) & S_out) = (unsigned)S_adj[0][S_in_16_a.b0];
285 S_out.b1 = (unsigned)S_adj[1][S_in_16_a.b1];
286 /* b2 spans two words */
287 S_out.b2 = (unsigned)
288 S_adj[2][(unsigned)S_in_16_a.b2 +
289 (((unsigned)S_in_16_b.b2) << 4)];
290 S_out.b3 = (unsigned)S_adj[3][S_in_16_b.b3];
291 S_out.b4 = (unsigned)S_adj[4][S_in_16_b.b4];
292 /* b5 spans both parts */
293 S_out.b5 = (unsigned)
294 S_adj[5][(unsigned)S_in_16_b.b5 +
295 (((unsigned)S_in_16_c.b5) << 2)];
296 S_out.b6 = (unsigned)S_adj[6][S_in_16_c.b6];
297 S_out.b7 = (unsigned)S_adj[7][S_in_16_c.b7];
300 /* is a 32 bit sys */
302 R2 = (unsigned)S_adj[0][L1 & 077];
303 L2 = (unsigned)S_adj[1][(L1 >> 6) & 077];
305 L2 = (unsigned)S_adj[2][(L1 >> 12) & 077];
307 L2 = (unsigned)S_adj[3][(L1 >> 18) & 077];
309 L2 = (unsigned)S_adj[4][(L1 >> 24) & 077];
311 /* b5 spans both parts */
313 S_adj[5][(unsigned)((L1 >> 30) & 03) + ((R1 & 017) << 2)];
315 L2 = (unsigned)S_adj[6][(R1 >> 4) & 077];
317 L2 = (unsigned)S_adj[7][(R1 >> 10) & 077];
318 R1 = R2 | (L2 << 28);
319 /* reset input to L1, R1 */
322 * this is the c code produced above, with
323 * extzv replaced by rotl
325 asm("bicl3 $-64,r9,r0");
326 asm("movzbl _S_adj[r0],r8");
327 asm("rotl $-6,r9,r0");
328 asm("bicl2 $-64,r0");
329 asm("movzbl _S_adj+64[r0],r7");
330 asm("ashl $4,r7,r0");
332 asm("rotl $-12,r9,r0");
333 asm("bicl2 $-64,r0");
334 asm("movzbl _S_adj+128[r0],r7");
335 asm("ashl $8,r7,r0");
337 asm("rotl $-18,r9,r0");
338 asm("bicl2 $-64,r0");
339 asm("movzbl _S_adj+192[r0],r7");
340 asm("ashl $12,r7,r0");
342 asm("rotl $-24,r9,r0");
343 asm("bicl2 $-64,r0");
344 asm("movzbl _S_adj+256[r0],r7");
345 asm("ashl $16,r7,r0");
347 asm("rotl $-30,r9,r0");
349 asm("bicl3 $-16,r10,r1");
350 asm("ashl $2,r1,r1");
352 asm("movzbl _S_adj+320[r0],r7");
353 asm("ashl $20,r7,r0");
355 asm("rotl $-4,r10,r0");
356 asm("bicl2 $-64,r0");
357 asm("movzbl _S_adj+384[r0],r7");
358 asm("ashl $24,r7,r0");
360 asm("rotl $-10,r10,r0");
361 asm("bicl2 $-64,r0");
362 asm("movzbl _S_adj+448[r0],r7");
363 asm("ashl $28,r7,r0");
374 DBG_PRINT("after s");
375 printf("iter = %2d after s\n\t\tL1 R1 = ", i);
376 des_cblock_print_file(dbg_tmp, stdout);
381 /* and then the p permutation from R1 into R2 */
383 /* reset the input to L1, R1 */
390 DBG_PRINT("after p");
391 printf("iter = %2d after p\n\t\tL1 R1 = ", i);
392 des_cblock_print_file(dbg_tmp, stdout);
396 /* R1 is the output value from the f() */
397 /* move R[iter] to L[iter+1] */
402 /* reset the input */
405 /* flip left and right before final permutation */
408 /* reset the input */
416 DBG_PRINT("before FP");
417 printf("iter = %2d before FP\n\t\tL1 R1 = ", i);
418 des_cblock_print_file(dbg_tmp, stdout);
423 /* do the final permutation from L1R1 to L2R2 */
424 /* all the fp code is in the include file */
427 /* copy the output to the ciphertext string;
428 * can be same as cleartext
432 if (afs_pointer_to_int(cipher) & 3) {
433 L_save = L2; /* cant bcopy a reg */
435 memcpy((char *)cipher, (char *)&L_save, sizeof(L_save));
436 cipher=((afs_uint32*)cipher)+1;
437 memcpy((char *)cipher, (char *)&R_save, sizeof(R_save));
441 *((afs_uint32*)cipher)= L2;
442 cipher = ((afs_int32 *)cipher)+1;
443 *((afs_uint32 *)cipher) = R2;
453 printf("iter = %2d done\n\t\tL1 R1 = ", i);
454 des_cblock_print_file(dbg_tmp, stdout);
458 /* that's it, no errors can be returned */