* $Source: /mit/kerberos/src/lib/des/RCS/des.c,v $
* Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
* For copying and distribution information, please see the file
* These routines perform encryption and decryption using the DES
* private key algorithm, or else a subset of it-- fewer inner loops.
* (AUTH_DES_ITER defaults to 16, may be less.)
* Under U.S. law, this software may not be exported outside the US
* without license from the U.S. Commerce department.
* The key schedule is passed as an arg, as well as the cleartext or
* All registers labeled imply Vax using the Ultrix or 4.2bsd
* NOTE: bit and byte numbering:
* DES algorithm is defined in terms of bits of L
* Always work in register pairs, FROM L1,R1 TO L2,R2 to make
* originally written by Steve Miller, MIT Project Athena
static char rcsid_des_c
[] =
"$Header: des.c,v 4.13 89/01/21 16:49:55 jtkohl Exp $";
#include <mit-copyright.h>
#include "des_internal.h"
#define DBG_PRINT(s) if (des_debug & 2) \
des_debug_print(s,i,L1&0xffff,(L1>>16)&0xffff, \
R1&0xffff,(R1>>16)&0xffff)
extern des_cblock_print_file ();
extern des_debug_print ();
des_ecb_encrypt(clear
, cipher
, schedule
, encrypt
)
int encrypt
; /* 0 ==> decrypt, else encrypt */
register des_key_schedule schedule
; /* r11 */
/* better pass 8 bytes, length not checked here */
register unsigned long R1
, L1
; /* R1 = r10, L1 = r9 */
register unsigned long R2
, L2
; /* R2 = r8, L2 = r7 */
/* one more registers left on VAX, see below P_temp_p */
unsigned int *S_in_a_16_p
= (unsigned int *) &S_in_16_a
;
unsigned int *S_in_b_16_p
= (unsigned int *) &S_in_16_b
;
unsigned int *S_in_c_16_p
= (unsigned int *) &S_in_16_c
;
dunno how to
do this machine type
, you lose
;
register unsigned char *P_temp_p
= (unsigned char *) & P_temp
;
unsigned long *S_out_p
= (unsigned long *) &S_out
;
unsigned long R_save
, L_save
;
unsigned long dbg_tmp
[2];
* Use L1,R1 and L2,R2 as two sets of "64-bit" registers always
* work from L1,R1 input to L2,R2 output; initialize the cleartext
* If the alignment is wrong, the programmer really screwed up --
* we aren't even getting the right data type. His problem. Keep
* this code for debugging.
/* Make sure schedule is ok */
if ((long) schedule
& 3) {
fprintf(stderr
,"des.c schedule arg pointer not aligned\n");
bcopy((char *)clear
++,(char *)&L_save
,sizeof(L_save
));
bcopy((char *)clear
,(char *)&R_save
,sizeof(R_save
));
if (clear
) L1
= *clear
++;
printf("All values printed from low byte (bit 0)");
printf(" --> high byte (bit 63)\n");
printf("iter = %2d before IP\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* all the Initial Permutation code is in the include file */
/* reset input to L1,R1 */
/* iterate through the inner loop */
for (i
= 0; i
<= (AUTH_DES_ITER
-1); i
++) {
printf("iter = %2d start loop\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* apply the E permutation from R1 to L2, R2 */
#else /* Bill's fast E */
L2
|= (R1
<<5) & 0770000;
L2
|= (R1
<<7) & 077000000;
L2
|= (R1
<<9) & 07700000000;
L2
|= (R1
<<11) & 030000000000;
/* now from right to right */
R2
= ((R1
>> 17) & 0176000);
if (R1
& (1<<0)) R2
|= 1<<15;
R2
|= ((R1
>> 21) & 017);
R2
|= ((R1
>> 19) & 01760);
L2
|= (R1
<<5) & 0770000;
L2
|= (R1
<<7) & 077000000;
L2
|= (R1
<<9) & 07700000000;
L2
|= (R1
<<11) & 030000000000;
asm(" rotl $-17,r10,r8");
asm(" rotl $-21,r10,r0");
asm(" rotl $-19,r10,r0");
/* reset input to L1,R1 */
printf("iter = %2d after e\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
* XOR with the key schedule, "schedule"
* If this is an encryption operation, use schedule[i],
* otherwise use schedule [AUTH_DES_ITER-i-1]
L1
^= *(((unsigned long *) &schedule
[i
] )+0);
R1
^= *(((unsigned long *) &schedule
[i
] )+1);
L1
^= *(((unsigned long *) &schedule
[AUTH_DES_ITER
-i
-1] )+0);
R1
^= *(((unsigned long *) &schedule
[AUTH_DES_ITER
-i
-1] )+1);
/* dont have to reset input to L1, R1 */
printf("iter = %2d after xor\n\t\tL1 R1 =",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* apply the S selection from L1, R1 to R2 */
/* S operations , cant use registers for bit field stuff */
*S_in_a_16_p
= L1
&0xffff;
*S_in_b_16_p
= (L1
>>16)&0xffff;
*S_in_c_16_p
= R1
&0xffff;
(*(unsigned long *) &S_out
) =
(unsigned) S_adj
[0][S_in_16_a
.b0
];
S_out
.b1
= (unsigned) S_adj
[1][S_in_16_a
.b1
];
S_adj
[2][(unsigned) S_in_16_a
.b2
+ (((unsigned) S_in_16_b
.b2
) << 4)];
S_out
.b3
= (unsigned) S_adj
[3][S_in_16_b
.b3
];
S_out
.b4
= (unsigned) S_adj
[4][S_in_16_b
.b4
];
/* b5 spans both parts */
S_adj
[5][(unsigned) S_in_16_b
.b5
+ (((unsigned) S_in_16_c
.b5
) << 2)];
S_out
.b6
= (unsigned) S_adj
[6][S_in_16_c
.b6
];
S_out
.b7
= (unsigned) S_adj
[7][S_in_16_c
.b7
];
R2
= (unsigned) S_adj
[0][L1
& 077];
L2
= (unsigned) S_adj
[1][(L1
>> 6) & 077];
L2
= (unsigned) S_adj
[2][(L1
>> 12) & 077];
L2
= (unsigned) S_adj
[3][(L1
>> 18) & 077];
L2
= (unsigned) S_adj
[4][(L1
>> 24) & 077];
/* b5 spans both parts */
S_adj
[5][(unsigned) ((L1
>>30) & 03) + ((R1
& 017) << 2)];
L2
= (unsigned) S_adj
[6][(R1
>> 4) & 077];
L2
= (unsigned) S_adj
[7][(R1
>> 10) & 077];
/* reset input to L1, R1 */
* this is the c code produced above, with
asm("movzbl _S_adj[r0],r8");
asm("movzbl _S_adj+64[r0],r7");
asm("movzbl _S_adj+128[r0],r7");
asm("movzbl _S_adj+192[r0],r7");
asm("movzbl _S_adj+256[r0],r7");
asm("bicl3 $-16,r10,r1");
asm("movzbl _S_adj+320[r0],r7");
asm("movzbl _S_adj+384[r0],r7");
asm("movzbl _S_adj+448[r0],r7");
printf("iter = %2d after s\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* and then the p permutation from R1 into R2 */
/* reset the input to L1, R1 */
printf("iter = %2d after p\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* R1 is the output value from the f() */
/* move R[iter] to L[iter+1] */
/* flip left and right before final permutation */
printf("iter = %2d before FP\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* do the final permutation from L1R1 to L2R2 */
/* all the fp code is in the include file */
/* copy the output to the ciphertext string;
* can be same as cleartext
L_save
= L2
; /* cant bcopy a reg */
bcopy((char *)&L_save
,(char *)cipher
++,sizeof(L_save
));
bcopy((char *)&R_save
,(char *)cipher
,sizeof(R_save
));
printf("iter = %2d done\n\t\tL1 R1 = ",i
);
des_cblock_print_file (dbg_tmp
, stdout
);
/* that's it, no errors can be returned */