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