pull-prototypes-to-head-20020821
[openafs.git] / src / des / des.c
1 /*
2  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
3  * of Technology.
4  *
5  * For copying and distribution information, please see the file
6  * <mit-cpyright.h>.
7  *
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.)
11  *
12  * Under U.S. law, this software may not be exported outside the US
13  * without license from the U.S. Commerce department.
14  *
15  * The key schedule is passed as an arg, as well as the cleartext or
16  * ciphertext.
17  *
18  * All registers labeled imply Vax using the Ultrix or 4.2bsd
19  * compiler.
20  *
21  *
22  *      NOTE:  bit and byte numbering:
23  *                      DES algorithm is defined in terms of bits of L
24  *                      followed by bits of R.
25
26  *              bit 0  ==> lsb of L
27  *              bit 63 ==> msb of R
28  *
29  * Always work in register pairs, FROM L1,R1 TO L2,R2 to make
30  * bookkeeping easier.
31  *
32  * originally written by Steve Miller, MIT Project Athena
33  */
34 #include <mit-cpyright.h>
35
36 #include <afsconfig.h>
37 #include <afs/param.h>
38
39 RCSID("$Header$");
40
41 #ifndef KERNEL
42 #include <stdio.h>
43 #endif
44 #ifdef AFS_PTHREAD_ENV
45 #include <pthread.h>
46 #endif /* AFS_PTHREAD_ENV */
47 #include <des.h>
48 #include "des_internal.h"
49 #include "s_table.h"
50 #ifdef BIG
51 #include "p_table.h"
52 #endif
53 #include "stats.h"
54
55 #include "des_prototypes.h"
56
57 #define XPRT_DES
58
59 #ifdef DEBUG
60 #define DBG_PRINT(s) if (des_debug & 2) \
61     des_debug_print(s,i,L1&0xffff,(L1>>16)&0xffff, \
62                 R1&0xffff,(R1>>16)&0xffff)
63 #else
64 #define DBG_PRINT(s)
65 #endif
66
67 #ifdef AFS_PTHREAD_ENV
68 pthread_mutex_t rxkad_stats_mutex;
69 #endif /* AFS_PTHREAD_ENV */
70     
71 /* encrypt == 0  ==> decrypt, else encrypt */
72
73 afs_int32 des_ecb_encrypt(afs_uint32 *clear, afs_uint32 *cipher, 
74         register des_key_schedule schedule, int encrypt)
75 {
76     /* better pass 8 bytes, length not checked here */
77
78     register afs_uint32 R1, L1; /* R1 = r10, L1 = r9 */
79     register afs_uint32 R2, L2; /* R2 = r8, L2 = r7 */
80     afs_int32 i;
81     /* one more registers left on VAX, see below P_temp_p */
82 #ifdef BITS16
83     sbox_in_16_a S_in_16_a;
84     sbox_in_16_b S_in_16_b;
85     sbox_in_16_c S_in_16_c;
86     unsigned int *S_in_a_16_p = (unsigned int *) &S_in_16_a;
87     unsigned int *S_in_b_16_p = (unsigned int *) &S_in_16_b;
88     unsigned int *S_in_c_16_p = (unsigned int *) &S_in_16_c;
89 #endif
90 #ifndef BITS32
91 #ifndef BITS16
92     dunno how to do this machine type, you lose;
93 #endif
94 #endif
95     afs_uint32 P_temp;
96     register unsigned char *P_temp_p = (unsigned char *) & P_temp;
97 #ifdef BITS16
98     sbox_out S_out;
99     afs_uint32 *S_out_p = (afs_uint32 *) &S_out;
100 #endif
101     afs_uint32 R_save, L_save;
102 #ifdef DEBUG
103     afs_uint32 dbg_tmp[2];
104 #endif
105     LOCK_RXKAD_STATS
106     if (encrypt) rxkad_stats.des_encrypts[DES_ENCRYPT]++;
107     else rxkad_stats.des_encrypts[DES_DECRYPT]++;
108     UNLOCK_RXKAD_STATS
109
110     /*
111      * Use L1,R1 and L2,R2 as two sets of "64-bit" registers always
112      * work from L1,R1 input to L2,R2 output; initialize the cleartext
113      * into registers.
114      */
115 #ifdef MUSTALIGN
116 #ifdef DEBUG
117     /*
118      * If the alignment is wrong, the programmer really screwed up --
119      * we aren't even getting the right data type.  His problem.  Keep
120      * this code for debugging.
121      */
122     /* Make sure schedule is ok */
123     if ((afs_int32) schedule & 3) {
124         fprintf(stderr,"des.c schedule arg pointer not aligned\n");
125         abort();
126     }
127 #endif
128     if ((afs_int32) clear & 3) {
129         memcpy((char *)&L_save, (char *)clear++, sizeof(L_save));
130         memcpy((char *)&R_save, (char *)clear, sizeof(R_save));
131         L1 = L_save;
132         R1 = R_save;
133     }
134     else
135 #endif
136     {
137         if (clear) L1 = *clear++;
138         else L1 = 0;
139         if (clear) R1 = *clear;
140         else R1 = 0;
141     }
142
143 #ifdef DEBUG
144     if (des_debug & 2) {
145         printf("All values printed from low byte (bit 0)");
146         printf(" --> high byte (bit 63)\n");
147         i = 0;
148         dbg_tmp[0] = L1;
149         dbg_tmp[1] = R1;
150         printf("iter = %2d  before IP\n\t\tL1 R1 = ",i);
151         des_cblock_print_file (dbg_tmp, stdout);
152     }
153
154     DBG_PRINT("before IP");
155 #endif
156
157 /*   IP_start:*/
158
159     /* all the Initial Permutation code is in the include file */
160 #include "ip.c"
161     /* reset input to L1,R1 */
162     L1 = L2;
163     R1 = R2;
164
165     /* iterate through the inner loop */
166     for (i = 0; i <= (AUTH_DES_ITER-1); i++) {
167
168 #ifdef DEBUG
169         if (des_debug & 2) {
170             dbg_tmp[0] = L1;
171             dbg_tmp[1] = R1;
172             printf("iter = %2d  start loop\n\t\tL1 R1 = ",i);
173             des_cblock_print_file (dbg_tmp, stdout);
174             DBG_PRINT("start loop");
175         }
176
177 #endif
178
179         R_save = R1;
180         L_save = L1;
181
182 /*   E_start:*/
183         /* apply the E permutation from R1 to L2, R2 */
184 #ifndef VAXASM
185 #ifdef SLOW_E
186 #include "e.c"
187 #else /* Bill's fast E */
188         L2 = (R1 << 1);
189         if (R1 & (1<<31))
190             L2 |= 1<<0;
191         L2 &= 077;
192         L2 |= (R1 <<3) & 07700;
193         L2 |= (R1 <<5) & 0770000;
194         L2 |= (R1 <<7) & 077000000;
195         L2 |= (R1 <<9) & 07700000000;
196         L2 |= (R1 <<11) & 030000000000;
197
198         /* now from right to right */
199
200         R2 = ((R1 >> 17) & 0176000);
201         if (R1 & (1<<0)) R2 |= 1<<15;
202
203         R2 |= ((R1 >> 21) & 017);
204         R2 |= ((R1 >> 19) & 01760);
205 #endif /* SLOW_E */
206 #else /* VAXASM */
207         /* E operations */
208         /* right to left */
209         asm("   rotl    $1,r10,r7");
210         L2 &= 077;
211         L2 |= (R1 <<3) & 07700;
212         L2 |= (R1 <<5) & 0770000;
213         L2 |= (R1 <<7) & 077000000;
214         L2 |= (R1 <<9) & 07700000000;
215         L2 |= (R1 <<11) & 030000000000;
216
217         asm("   rotl    $-17,r10,r8");
218         R2 &= 0176000;
219         asm("   rotl    $-21,r10,r0");
220         asm("   bicl2   $-16,r0");
221         asm("  bisl2    r0,r8");
222         asm("   rotl    $-19,r10,r0");
223         asm("   bicl2   $-1009,r0");
224         asm("  bisl2    r0,r8");
225
226 #endif
227
228         /* reset input to L1,R1 */
229         L1 = L2;
230         R1 = R2;
231
232 #ifdef DEBUG
233         if (des_debug & 2) {
234             dbg_tmp[0] = L1;
235             dbg_tmp[1] = R1;
236             DBG_PRINT("after e");
237             printf("iter = %2d  after e\n\t\tL1 R1 = ",i);
238             des_cblock_print_file (dbg_tmp, stdout);
239         }
240 #endif
241
242 /*   XOR_start:*/
243         /*
244          * XOR with the key schedule, "schedule"
245          *
246          * If this is an encryption operation, use schedule[i],
247          * otherwise use schedule [AUTH_DES_ITER-i-1]
248          *
249          * First XOR left half.
250          */
251         if (encrypt) {
252             L1 ^= *(((afs_uint32 *) &schedule[i] )+0);
253             /* now right half */
254             R1 ^= *(((afs_uint32 *) &schedule[i] )+1);
255         }
256         else {
257             L1 ^= *(((afs_uint32 *) &schedule[AUTH_DES_ITER-i-1] )+0);
258             /* now right half */
259             R1 ^= *(((afs_uint32 *) &schedule[AUTH_DES_ITER-i-1] )+1);
260         }
261
262         /* dont have to reset input to L1, R1 */
263
264 #ifdef DEBUG
265         if (des_debug & 2) {
266             dbg_tmp[0] = L1;
267             dbg_tmp[1] = R1;
268             DBG_PRINT("after xor");
269             printf("iter = %2d  after xor\n\t\tL1 R1 =",i);
270             des_cblock_print_file (dbg_tmp, stdout);
271         }
272 #endif
273
274 /*   S_start:*/
275         /* apply the S selection from L1, R1 to R2 */
276
277 #ifdef notdef
278 #include "s.c"
279 #endif
280
281         /* S operations , cant use registers for bit field stuff */
282         /* from S_in to S_out */
283
284 #ifdef BITS16
285         *S_in_a_16_p = L1&0xffff;
286         *S_in_b_16_p = (L1>>16)&0xffff;
287         *S_in_c_16_p = R1&0xffff;
288         (*(afs_uint32 *) &S_out) =
289             (unsigned) S_adj[0][S_in_16_a.b0];
290         S_out.b1 = (unsigned) S_adj[1][S_in_16_a.b1];
291         /* b2 spans two words */
292         S_out.b2 = (unsigned)
293             S_adj[2][(unsigned) S_in_16_a.b2
294                      + (((unsigned) S_in_16_b.b2) << 4)];
295         S_out.b3 = (unsigned) S_adj[3][S_in_16_b.b3];
296         S_out.b4 = (unsigned) S_adj[4][S_in_16_b.b4];
297         /* b5 spans both parts */
298         S_out.b5 = (unsigned)
299             S_adj[5][(unsigned) S_in_16_b.b5
300                      + (((unsigned) S_in_16_c.b5) << 2)];
301         S_out.b6 = (unsigned) S_adj[6][S_in_16_c.b6];
302         S_out.b7 = (unsigned) S_adj[7][S_in_16_c.b7];
303         R1 = *S_out_p;
304 #else
305         /* is a 32 bit sys */
306 #ifndef VAXASM
307         R2 =  (unsigned) S_adj[0][L1 & 077];
308         L2 = (unsigned) S_adj[1][(L1 >> 6) & 077];
309         R2 |= (L2 <<4 );
310         L2 = (unsigned) S_adj[2][(L1 >> 12) & 077];
311         R2 |= (L2 <<8);
312         L2 = (unsigned) S_adj[3][(L1 >> 18) & 077];
313         R2 |= (L2 <<12);
314         L2 = (unsigned) S_adj[4][(L1 >> 24) & 077];
315         R2 |= (L2 <<16);
316         /* b5 spans both parts */
317         L2 = (unsigned)
318             S_adj[5][(unsigned) ((L1 >>30) & 03) + ((R1 & 017) << 2)];
319         R2 |= (L2 << 20);
320         L2 = (unsigned) S_adj[6][(R1 >> 4) & 077];
321         R2 |= (L2 <<24);
322         L2 = (unsigned) S_adj[7][(R1 >> 10) & 077];
323         R1 = R2 | (L2 <<28);
324         /* reset input to L1, R1 */
325 #else /* vaxasm */
326         /*
327          * this is the c code produced above, with
328          * extzv replaced by rotl
329          */
330         asm("bicl3      $-64,r9,r0");
331         asm("movzbl     _S_adj[r0],r8");
332         asm("rotl       $-6,r9,r0");
333         asm("bicl2      $-64,r0");
334         asm("movzbl     _S_adj+64[r0],r7");
335         asm("ashl       $4,r7,r0");
336         asm("bisl2      r0,r8");
337         asm("rotl       $-12,r9,r0");
338         asm("bicl2      $-64,r0");
339         asm("movzbl     _S_adj+128[r0],r7");
340         asm("ashl       $8,r7,r0");
341         asm("bisl2      r0,r8");
342         asm("rotl       $-18,r9,r0");
343         asm("bicl2      $-64,r0");
344         asm("movzbl     _S_adj+192[r0],r7");
345         asm("ashl       $12,r7,r0");
346         asm("bisl2      r0,r8");
347         asm("rotl       $-24,r9,r0");
348         asm("bicl2      $-64,r0");
349         asm("movzbl     _S_adj+256[r0],r7");
350         asm("ashl       $16,r7,r0");
351         asm("bisl2      r0,r8");
352         asm("rotl       $-30,r9,r0");
353         asm("bicl2      $-4,r0");
354         asm("bicl3      $-16,r10,r1");
355         asm("ashl       $2,r1,r1");
356         asm("addl2      r1,r0");
357         asm("movzbl     _S_adj+320[r0],r7");
358         asm("ashl       $20,r7,r0");
359         asm("bisl2      r0,r8");
360         asm("rotl       $-4,r10,r0");
361         asm("bicl2      $-64,r0");
362         asm("movzbl     _S_adj+384[r0],r7");
363         asm("ashl       $24,r7,r0");
364         asm("bisl2      r0,r8");
365         asm("rotl       $-10,r10,r0");
366         asm("bicl2      $-64,r0");
367         asm("movzbl     _S_adj+448[r0],r7");
368         asm("ashl       $28,r7,r0");
369         asm("bisl2      r8,r0");
370         asm("movl       r0,r10");
371
372 #endif /* vaxasm */
373 #endif
374
375 #ifdef DEBUG
376         if (des_debug & 2) {
377             dbg_tmp[0] = L1;
378             dbg_tmp[1] = R1;
379             DBG_PRINT("after s");
380             printf("iter = %2d  after s\n\t\tL1 R1 = ",i);
381             des_cblock_print_file (dbg_tmp, stdout);
382         }
383 #endif
384
385 /*   P_start:*/
386         /* and then the p permutation from R1 into R2 */
387 #include "p.c"
388         /* reset the input to L1, R1 */
389         R1 = R2;
390
391 #ifdef DEBUG
392         if (des_debug & 2) {
393             dbg_tmp[0] = L1;
394             dbg_tmp[1] = R1;
395             DBG_PRINT("after p");
396             printf("iter = %2d  after p\n\t\tL1 R1 = ",i);
397             des_cblock_print_file (dbg_tmp, stdout);
398         }
399 #endif
400
401         /* R1 is the output value from the f() */
402         /* move R[iter] to L[iter+1] */
403 /*   XOR_2_start:*/
404         L1 = R_save;
405         /* xor with left */
406         R1 = L_save ^ R1;
407         /* reset the input */
408     }
409
410     /* flip left and right before final permutation */
411     L2 = R1;                    /* flip */
412     R2 = L1;
413     /* reset the input */
414     L1 = L2;
415     R1 = R2;
416
417 #ifdef DEBUG
418     if (des_debug & 2) {
419         dbg_tmp[0] = L1;
420         dbg_tmp[1] = R1;
421         DBG_PRINT("before FP");
422         printf("iter = %2d  before FP\n\t\tL1 R1 = ",i);
423         des_cblock_print_file (dbg_tmp, stdout);
424     }
425
426 #endif
427
428 /*FP_start:*/
429     /* do the final permutation from L1R1 to L2R2 */
430     /* all the fp code is in the include file */
431 #include "fp.c"
432
433     /* copy the output to the ciphertext string;
434      * can be same as cleartext
435      */
436
437 #ifdef MUSTALIGN
438     if ((afs_int32) cipher & 3) {
439         L_save = L2;    /* cant bcopy a reg */
440         R_save = R2;
441         memcpy((char *)cipher++, (char *)&L_save, sizeof(L_save));
442         memcpy((char *)cipher, (char *)&R_save, sizeof(R_save));
443     }
444     else
445 #endif
446     {
447         *cipher++ = L2;
448         *cipher = R2;
449     }
450
451 #ifdef DEBUG
452     if (des_debug & 2) {
453         L1 = L2;
454         R1 = R2;
455         dbg_tmp[0] = L1;
456         dbg_tmp[1] = R1;
457         DBG_PRINT("done");
458         printf("iter = %2d  done\n\t\tL1 R1 = ",i);
459         des_cblock_print_file (dbg_tmp, stdout);
460     }
461 #endif
462
463     /* that's it, no errors can be returned */
464     return 0;
465 }
466