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