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