Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / des / key_sched.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  * This routine computes the DES key schedule given a key.  The
9  * permutations and shifts have been done at compile time, resulting
10  * in a direct one-step mapping from the input key to the key
11  * schedule.
12  *
13  * Also checks parity and weak keys.
14  *
15  * Watch out for the subscripts -- most effectively start at 1 instead
16  * of at zero.  Maybe some bugs in that area.
17  *
18  * DON'T change the data types for arrays and such, or it will either
19  * break or run slower.  This was optimized for Uvax2.
20  *
21  * In case the user wants to cache the computed key schedule, it is
22  * passed as an arg.  Also implies that caller has explicit control
23  * over zeroing both the key schedule and the key.
24  *
25  * All registers labeled imply Vax using the Ultrix or 4.2bsd compiler.
26  *
27  * Originally written 6/85 by Steve Miller, MIT Project Athena.
28  */
29
30 #include <mit-cpyright.h>
31 #include "des_internal.h"
32 #include <stdio.h>
33
34 #include "des.h"
35 #include "key_perm.h"
36 #include "stats.h"
37
38 extern int des_debug;
39 extern rev_swap_bit_pos_0();
40
41 typedef char key[64];
42 /* the following are really void but cc86 doesnt allow it */
43 static int make_key_sched();
44
45 #ifdef AFS_DUX40_ENV
46 #pragma weak des_key_sched = afs_des_key_sched
47 int afs_des_key_sched(k,schedule)
48 #else
49 int des_key_sched(k,schedule)
50 #endif
51     register des_cblock k;      /* r11 */
52     des_key_schedule schedule;
53 {
54     /* better pass 8 bytes, length not checked here */
55
56     register int i, j, n;               /* i = r10, j = r9, n = r8 */
57     register unsigned int temp; /*  r7 */
58     register char *p_char;      /* r6 */
59     key k_char;
60     i = 8;
61     n = 0;
62     p_char = k_char;
63
64     LOCK_RXKAD_STATS
65     rxkad_stats.des_key_scheds++;
66     UNLOCK_RXKAD_STATS
67
68 #ifdef lint
69     n = n;                              /* fool it in case of VAXASM */
70 #endif
71 #ifdef DEBUG
72     if (des_debug)
73         fprintf(stderr,"\n\ninput key, left to right = ");
74 #endif
75
76     if (!des_check_key_parity(k))       /* bad parity --> return -1 */
77         return(-1);
78
79     do {
80         /* get next input key byte */
81 #ifdef DEBUG
82         if (des_debug)
83             fprintf(stderr,"%02x ",*k & 0xff);
84 #endif
85         temp = (unsigned int) ((unsigned char) *k++);
86         j = 8;
87
88         do {
89 #ifndef VAXASM
90             *p_char++ = (int) temp & 01;
91             temp = temp >> 1;
92 #else
93             asm("bicb3  $-2,r7,(r8)+[r6]");
94             asm("rotl   $-1,r7,r7");
95 #endif
96         } while (--j > 0);
97     } while (--i > 0);
98
99 #ifdef DEBUG
100     if (des_debug) {
101         p_char = k_char;
102         fprintf(stderr,"\nKey bits, from zero to 63");
103         for (i = 0; i <= 7; i++) {
104             fprintf(stderr,"\n\t");
105             for (j = 0; j <=7; j++)
106                 fprintf(stderr,"%d ",*p_char++);
107         }
108     }
109 #else
110 #ifdef lint
111     p_char = p_char;
112 #endif
113 #endif
114
115     /* check against weak keys */
116     k -= sizeof(des_cblock);
117
118     if (des_is_weak_key(k))
119         return(-2);
120
121     make_key_sched(k_char,schedule);
122
123     /* if key was good, return 0 */
124     return 0;
125 }
126
127 static int
128 make_key_sched(Key,Schedule)
129     register key Key;           /* r11 */
130     des_key_schedule Schedule;
131 {
132     /*
133      * The key has been converted to an array to make this run faster;
134      * on a microvax 2, this routine takes about 3.5ms.  The code and
135      * size of the arrays has been played with to get it as fast as
136      * possible.
137      *
138      * Don't change the order of the declarations below without
139      * checking the assembler code to make sure that things are still
140      * where it expects them.
141      */
142
143     /* r10, unroll by AUTH_DES_ITER */
144     register int iter = AUTH_DES_ITER ;
145     register afs_uint32 *k;      /* r9 */
146     register int *kp;            /* r8 */
147     register afs_uint32 temp; /* r7 */
148
149     kp = (int *) key_perm;
150     k  = (afs_uint32 *) Schedule;
151
152     do {
153         /*
154          * create the Key schedule
155          *
156          * put into lsb first order (lsb is bit 0)
157          */
158
159         /*
160          * On the uvax2, this C code below is as fast as straight
161          * assembler, so just use C code below.
162          */
163         temp = 0;
164 #ifdef LSBFIRST
165 #define BIT(x)  x
166 #else
167 #ifdef notdef
168 #define BIT(x) rev_swap_bit_pos_0(x)
169 #else
170 #define BIT(x)  x
171 #endif
172 #endif
173         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(0));
174         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(1));
175         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(2));
176         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(3));
177         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(4));
178         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(5));
179         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(6));
180         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(7));
181
182         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(8));
183         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(9));
184         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(10));
185         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(11));
186         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(12));
187         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(13));
188         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(14));
189         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(15));
190
191         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(16));
192         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(17));
193         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(18));
194         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(19));
195         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(20));
196         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(21));
197         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(22));
198         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(23));
199
200         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(24));
201         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(25));
202         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(26));
203         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(27));
204         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(28));
205         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(29));
206         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(30));
207         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(31));
208
209         *k++ = temp;
210         temp = 0;
211
212         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(0));
213         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(1));
214         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(2));
215         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(3));
216         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(4));
217         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(5));
218         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(6));
219         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(7));
220
221         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(8));
222         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(9));
223         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(10));
224         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(11));
225         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(12));
226         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(13));
227         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(14));
228         if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(15));
229
230         *k++ = temp;
231
232     } while (--iter > 0);
233
234 #ifdef DEBUG
235     if (des_debug) {
236         int i;
237         char *n;
238         int q;
239         fprintf(stderr,"\nKey Schedule, left to right");
240         for (i = 0; i < AUTH_DES_ITER; i++) {
241             n = (char *) &Schedule[i];
242             fprintf(stderr,"\n");
243             for (q = 0; q <= 7; q++)
244                 fprintf(stderr,"%02x ",*n++ & 0xff);
245         }
246         fprintf(stderr,"\n");
247     }
248 #endif
249 }