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