2 * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
5 * For copying and distribution information, please see the file
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
13 * Also checks parity and weak keys.
15 * Watch out for the subscripts -- most effectively start at 1 instead
16 * of at zero. Maybe some bugs in that area.
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.
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.
25 * All registers labeled imply Vax using the Ultrix or 4.2bsd compiler.
27 * Originally written 6/85 by Steve Miller, MIT Project Athena.
30 #include <mit-cpyright.h>
31 #include "des_internal.h"
39 extern rev_swap_bit_pos_0();
42 /* the following are really void but cc86 doesnt allow it */
43 static int make_key_sched();
46 #pragma weak des_key_sched = afs_des_key_sched
47 int afs_des_key_sched(k,schedule)
49 int des_key_sched(k,schedule)
51 register des_cblock k; /* r11 */
52 des_key_schedule schedule;
54 /* better pass 8 bytes, length not checked here */
56 register int i, j, n; /* i = r10, j = r9, n = r8 */
57 register unsigned int temp; /* r7 */
58 register char *p_char; /* r6 */
65 rxkad_stats.des_key_scheds++;
69 n = n; /* fool it in case of VAXASM */
73 fprintf(stderr,"\n\ninput key, left to right = ");
76 if (!des_check_key_parity(k)) /* bad parity --> return -1 */
80 /* get next input key byte */
83 fprintf(stderr,"%02x ",*k & 0xff);
85 temp = (unsigned int) ((unsigned char) *k++);
90 *p_char++ = (int) temp & 01;
93 asm("bicb3 $-2,r7,(r8)+[r6]");
94 asm("rotl $-1,r7,r7");
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++);
115 /* check against weak keys */
116 k -= sizeof(des_cblock);
118 if (des_is_weak_key(k))
121 make_key_sched(k_char,schedule);
123 /* if key was good, return 0 */
128 make_key_sched(Key,Schedule)
129 register key Key; /* r11 */
130 des_key_schedule Schedule;
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
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.
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 */
149 kp = (int *) key_perm;
150 k = (afs_uint32 *) Schedule;
154 * create the Key schedule
156 * put into lsb first order (lsb is bit 0)
160 * On the uvax2, this C code below is as fast as straight
161 * assembler, so just use C code below.
168 #define BIT(x) rev_swap_bit_pos_0(x)
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));
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));
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));
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));
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));
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));
232 } while (--iter > 0);
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);
246 fprintf(stderr,"\n");