source: trunk/sys/dietlibc/crypt.c @ 5

Last change on this file since 5 was 1, checked in by alain, 8 years ago

First import

File size: 7.9 KB
Line 
1#include "dietfeatures.h"
2#include <unistd.h>
3#include <md5.h>
4
5/* Initial permutation, */
6static const char IP[] = {
7  57,49,41,33,25,17, 9, 1,
8  59,51,43,35,27,19,11, 3,
9  61,53,45,37,29,21,13, 5,
10  63,55,47,39,31,23,15, 7,
11  56,48,40,32,24,16, 8, 0,
12  58,50,42,34,26,18,10, 2,
13  60,52,44,36,28,20,12, 4,
14  62,54,46,38,30,22,14, 6
15};
16
17/* Final permutation, FP = IP^(-1) */
18static const char FP[] = {
19  39, 7,47,15,55,23,63,31,
20  38, 6,46,14,54,22,62,30,
21  37, 5,45,13,53,21,61,29,
22  36, 4,44,12,52,20,60,28,
23  35, 3,43,11,51,19,59,27,
24  34, 2,42,10,50,18,58,26,
25  33, 1,41, 9,49,17,57,25,
26  32, 0,40, 8,48,16,56,24
27};
28
29/* Permuted-choice 1 from the key bits to yield C and D.
30 * Note that bits 8,16... are left out: They are intended for a parity check.
31 */
32static const char PC1_C[] = {
33  56,48,40,32,24,16, 8,
34   0,57,49,41,33,25,17,
35   9, 1,58,50,42,34,26,
36  18,10, 2,59,51,43,35
37};
38
39static const char PC1_D[] = {
40  62,54,46,38,30,22,14,
41   6,61,53,45,37,29,21,
42  13, 5,60,52,44,36,28,
43  20,12, 4,27,19,11, 3
44};
45
46/* Sequence of shifts used for the key schedule. */
47static const char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
48
49/*
50 * Permuted-choice 2, to pick out the bits from the CD array that generate
51 * the key schedule.
52 */
53static const char PC2_C[] = {
54  13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
55  22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1
56};
57
58static const char PC2_D[] = {
59  12, 23,  2,  8, 18, 26,  1, 11, 22, 16,  4, 19,
60  15, 20, 10, 27,  5, 24, 17, 13, 21,  7,  0,  3
61};
62
63/* The C and D arrays used to calculate the key schedule. */
64
65static char C[28];
66static char D[28];
67/* The key schedule. Generated from the key. */
68static char KS[16][48];
69
70/* The E bit-selection table. */
71static char E[48];
72static const char e2[] = {
73  32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
74   8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
75  16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
76  24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
77};
78
79/* Set up the key schedule from the key. */
80void setkey(const char *key)
81{
82  register int i, j, k;
83  int  t;
84  int  s;
85
86  /* First, generate C and D by permuting the key.  The low order bit of each
87   * 8-bit char is not used, so C and D are only 28 bits apiece.
88   */
89  for(i=0; i < 28; i++) {
90    C[i] = key[(int)PC1_C[i]];
91    D[i] = key[(int)PC1_D[i]];
92  }
93  /* To generate Ki, rotate C and D according to schedule and pick up a
94   * permutation using PC2.
95   */
96  for(i=0; i < 16; i++) {
97    /* rotate. */
98    s = shifts[i];
99    for(k=0; k < s; k++) {
100      t = C[0];
101      for(j=0; j < 27; j++)
102        C[j] = C[j+1];
103      C[27] = t;
104      t = D[0];
105      for(j=0; j < 27; j++)
106        D[j] = D[j+1];
107      D[27] = t;
108    }
109    /* get Ki. Note C and D are concatenated. */
110    for(j=0; j < 24; j++) {
111      KS[i][j] = C[(int)PC2_C[j]];
112      KS[i][j+24] = D[(int)PC2_D[j]];
113    }
114  }
115
116  for(i=0; i < 48; i++)
117    E[i] = e2[i];
118}
119
120/* The 8 selection functions. For some reason, they give a 0-origin index,
121 * unlike everything else.
122 */
123static const char S[8][64] = {
124  {
125    14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
126     0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
127     4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
128    15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13
129  },
130
131  {
132    15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
133     3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
134     0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
135    13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9
136  },
137
138  {
139    10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
140    13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
141    13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
142     1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12
143  },
144
145  {
146     7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
147    13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
148    10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
149     3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14
150  },
151
152  {
153     2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
154    14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
155     4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
156    11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3
157  },
158
159  {
160    12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
161    10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
162     9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
163     4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13
164  },
165
166  {
167     4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
168    13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
169     1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
170     6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12
171  },
172
173  {
174    13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
175     1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
176     7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
177     2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11
178  }
179};
180
181/* P is a permutation on the selected combination of the current L and key. */
182static const char P[] = {
183  15, 6,19,20, 28,11,27,16,  0,14,22,25,  4,17,30, 9,
184   1, 7,23,13, 31,26, 2, 8, 18,12,29, 5, 21,10, 3,24
185};
186
187/* The current block, divided into 2 halves. */
188static char L[64];
189#define R (L+32)
190static char tempL[32];
191static char f[32];
192
193/* The combination of the key and the input, before selection. */
194static char preS[48];
195
196/* The payoff: encrypt a block. */
197void encrypt(char block[64],int edflag)
198{
199  int  i, ii;
200  register int t, j, k;
201
202  (void)edflag;
203  /* First, permute the bits in the input */
204  for(j=0; j < 64; j++)
205    L[j] = block[(int)IP[j]];
206  /* Perform an encryption operation 16 times. */
207  for(ii=0; ii < 16; ii++) {
208    i = ii;
209    /* Save the R array, which will be the new L. */
210    for(j=0; j < 32; j++)
211      tempL[j] = R[j];
212    /* Expand R to 48 bits using the E selector;
213     * exclusive-or with the current key bits.
214     */
215    for(j=0; j < 48; j++)
216      preS[j] = R[E[j]-1] ^ KS[i][j];
217    /* The pre-select bits are now considered in 8 groups of 6 bits each.
218     * The 8 selection functions map these 6-bit quantities into 4-bit
219     * quantities and the results permuted to make an f(R, K).
220     * The indexing into the selection functions is peculiar;
221     * it could be simplified by rewriting the tables.
222     */
223    for(j=0; j < 8; j++) {
224      t = ((j<<1)+j)<<1;
225      k = S[j][(preS[t]<<5)+
226         (preS[t+1]<<3)+
227         (preS[t+2]<<2)+
228         (preS[t+3]<<1)+
229         (preS[t+4]   )+
230         (preS[t+5]<<4)];
231      t = j << 2;
232      f[] = (k>>3)&01;
233      f[t+1] = (k>>2)&01;
234      f[t+2] = (k>>1)&01;
235      f[t+3] = (k   )&01;
236    }
237    /* The new R is L ^ f(R, K). The f here has to be permuted first, though. */
238    for(j=0; j < 32; j++)
239      R[j] = L[j] ^ f[(int)P[j]];
240    /* Finally, the new L (the original R) is copied back. */
241    for(j=0; j < 32; j++)
242      L[j] = tempL[j];
243  }
244  /* The output L and R are reversed. */
245  for(j=0; j < 32; j++) {
246    L[j] ^= R[j];
247    R[j] ^= L[j];
248    L[j] ^= R[j];
249  }
250  /* The final output gets the inverse permutation of the very original. */
251  for(j=0; j < 64; j++)
252    block[j] = L[(int)FP[j]];
253}
254
255char * crypt(const char *pw, const char *salt)
256{
257  register int i, j, c;
258  static char block[66], iobuf[16];
259#ifdef WANT_CRYPT_MD5
260  if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$')
261    return md5crypt(pw,salt);
262#endif
263  for(i=0; i < 66; i++)
264    block[i] = 0;
265  for(i=0; (c= *pw) && i < 64; pw++) {
266    for(j=0; j < 7; j++, i++)
267      block[i] = (c>>(6-j)) & 01;
268    i++;
269  }
270
271  setkey(block);
272
273  for(i=0; i < 66; i++)
274    block[i] = 0;
275
276  for(i=0; i < 2; i++) {
277    c = *salt++;
278    iobuf[i] = c;
279    if(c > 'Z')
280      c -= 6;
281    if(c > '9')
282      c -= 7;
283    c -= '.';
284    for(j=0; j < 6; j++) {
285      if((c>>j) & 01) {
286        int ind1 = (((i<<1)+i)<< 1) + j;
287        int ind2 = ind1 + 24;
288        E[ind1] ^= E[ind2];
289        E[ind2] ^= E[ind1];
290        E[ind1] ^= E[ind2];
291      }
292    }
293  }
294
295  for(i=0; i < 25; i++)
296    encrypt(block,0);
297
298  for(i=0; i < 11; i++) {
299    c = 0;
300    for(j=0; j < 6; j++) {
301      c <<= 1;
302      c |= block[(((i<<1)+i)<<1)+j];
303    }
304    c += '.';
305    if(c > '9')
306      c += 7;
307    if(c > 'Z')
308      c += 6;
309    iobuf[i+2] = c;
310  }
311  iobuf[i+2] = 0;
312  if(iobuf[1] == 0)
313    iobuf[1] = iobuf[0];
314  return(iobuf);
315}
Note: See TracBrowser for help on using the repository browser.