Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / camel / camel-sasl-ntlm.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright 2002 Ximian, Inc. (www.ximian.com)
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU Lesser General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <ctype.h>
26 #include <string.h>
27
28 #include <glib.h>
29 #include <glib/gi18n-lib.h>
30
31 #include "camel-sasl-ntlm.h"
32
33 CamelServiceAuthType camel_sasl_ntlm_authtype = {
34         N_("NTLM / SPA"),
35
36         N_("This option will connect to a Windows-based server using "
37            "NTLM / Secure Password Authentication."),
38
39         "NTLM",
40         TRUE
41 };
42
43 static CamelSaslClass *parent_class = NULL;
44
45 static GByteArray *ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex);
46
47 static void
48 camel_sasl_ntlm_class_init (CamelSaslNTLMClass *camel_sasl_ntlm_class)
49 {
50         CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_ntlm_class);
51         
52         parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
53         
54         /* virtual method overload */
55         camel_sasl_class->challenge = ntlm_challenge;
56 }
57
58 CamelType
59 camel_sasl_ntlm_get_type (void)
60 {
61         static CamelType type = CAMEL_INVALID_TYPE;
62
63         if (type == CAMEL_INVALID_TYPE) {
64                 type = camel_type_register (
65                         camel_sasl_get_type (), "CamelSaslNTLM",
66                         sizeof (CamelSaslNTLM),
67                         sizeof (CamelSaslNTLMClass),
68                         (CamelObjectClassInitFunc) camel_sasl_ntlm_class_init,
69                         NULL, NULL, NULL);
70         }
71
72         return type;
73 }
74
75 #define NTLM_REQUEST "NTLMSSP\x00\x01\x00\x00\x00\x06\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00"
76
77 #define NTLM_CHALLENGE_NONCE_OFFSET      24
78 #define NTLM_CHALLENGE_DOMAIN_OFFSET     48
79 #define NTLM_CHALLENGE_DOMAIN_LEN_OFFSET 44
80
81 #define NTLM_RESPONSE_HEADER         "NTLMSSP\x00\x03\x00\x00\x00"
82 #define NTLM_RESPONSE_FLAGS          "\x82\x01"
83 #define NTLM_RESPONSE_BASE_SIZE      64
84 #define NTLM_RESPONSE_LM_RESP_OFFSET 12
85 #define NTLM_RESPONSE_NT_RESP_OFFSET 20
86 #define NTLM_RESPONSE_DOMAIN_OFFSET  28
87 #define NTLM_RESPONSE_USER_OFFSET    36
88 #define NTLM_RESPONSE_HOST_OFFSET    44
89 #define NTLM_RESPONSE_FLAGS_OFFSET   60
90
91 static void ntlm_calc_response   (const guchar key[21],
92                                   const guchar plaintext[8],
93                                   guchar results[24]);
94 static void ntlm_lanmanager_hash (const char *password, char hash[21]);
95 static void ntlm_nt_hash         (const char *password, char hash[21]);
96 static void ntlm_set_string      (GByteArray *ba, int offset,
97                                   const char *data, int len);
98
99 static GByteArray *
100 ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
101 {
102         GByteArray *ret;
103         guchar nonce[8], hash[21], lm_resp[24], nt_resp[24];
104
105         ret = g_byte_array_new ();
106
107         if (!token || !token->len) {
108                 g_byte_array_append (ret, NTLM_REQUEST,
109                                      sizeof (NTLM_REQUEST) - 1);
110                 return ret;
111         }
112
113         memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8);
114         ntlm_lanmanager_hash (sasl->service->url->passwd, hash);
115         ntlm_calc_response (hash, nonce, lm_resp);
116         ntlm_nt_hash (sasl->service->url->passwd, hash);
117         ntlm_calc_response (hash, nonce, nt_resp);
118
119         ret = g_byte_array_new ();
120         g_byte_array_set_size (ret, NTLM_RESPONSE_BASE_SIZE);
121         memset (ret->data, 0, NTLM_RESPONSE_BASE_SIZE);
122         memcpy (ret->data, NTLM_RESPONSE_HEADER,
123                 sizeof (NTLM_RESPONSE_HEADER) - 1);
124         memcpy (ret->data + NTLM_RESPONSE_FLAGS_OFFSET,
125                 NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1);
126
127         ntlm_set_string (ret, NTLM_RESPONSE_DOMAIN_OFFSET,
128                          token->data + NTLM_CHALLENGE_DOMAIN_OFFSET,
129                          atoi (token->data + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET));
130         ntlm_set_string (ret, NTLM_RESPONSE_USER_OFFSET,
131                          sasl->service->url->user,
132                          strlen (sasl->service->url->user));
133         ntlm_set_string (ret, NTLM_RESPONSE_HOST_OFFSET,
134                          "UNKNOWN", sizeof ("UNKNOWN") - 1);
135         ntlm_set_string (ret, NTLM_RESPONSE_LM_RESP_OFFSET,
136                          lm_resp, sizeof (lm_resp));
137         ntlm_set_string (ret, NTLM_RESPONSE_NT_RESP_OFFSET,
138                          nt_resp, sizeof (nt_resp));
139
140         sasl->authenticated = TRUE;
141         return ret;
142 }
143
144 /* MD4 */
145 static void md4sum                (const unsigned char *in, 
146                                    int                  nbytes, 
147                                    unsigned char        digest[16]);
148
149 /* DES */
150 typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */
151
152 static void deskey                (DES_KS, unsigned char *, int);
153
154 static void des                   (DES_KS, unsigned char *);
155
156 static void setup_schedule        (const guchar *key_56, DES_KS ks);
157
158
159
160 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
161                           "\x4B\x47\x53\x21\x40\x23\x24\x25" \
162                           "\x00\x00\x00\x00\x00"
163
164 static void
165 ntlm_lanmanager_hash (const char *password, char hash[21])
166 {
167         guchar lm_password [15];
168         DES_KS ks;
169         int i;
170
171         for (i = 0; i < 14 && password [i]; i++)
172                 lm_password [i] = toupper ((unsigned char) password [i]);
173
174         for (; i < 15; i++)
175                 lm_password [i] = '\0';
176
177         memcpy (hash, LM_PASSWORD_MAGIC, 21);
178
179         setup_schedule (lm_password, ks);
180         des (ks, hash);
181
182         setup_schedule (lm_password + 7, ks);
183         des (ks, hash + 8);
184 }
185
186 static void
187 ntlm_nt_hash (const char *password, char hash[21])
188 {
189         unsigned char *buf, *p;
190
191         p = buf = g_malloc (strlen (password) * 2);
192
193         while (*password) {
194                 *p++ = *password++;
195                 *p++ = '\0';
196         }
197
198         md4sum (buf, p - buf, hash);
199         memset (hash + 16, 0, 5);
200
201         g_free (buf);
202 }
203
204 static void
205 ntlm_set_string (GByteArray *ba, int offset, const char *data, int len)
206 {
207         ba->data[offset    ] = ba->data[offset + 2] =  len       & 0xFF;
208         ba->data[offset + 1] = ba->data[offset + 3] = (len >> 8) & 0xFF;
209         ba->data[offset + 4] =  ba->len       & 0xFF;
210         ba->data[offset + 5] = (ba->len >> 8) & 0xFF;
211         g_byte_array_append (ba, data, len);
212 }
213
214
215 #define KEYBITS(k,s) \
216         (((k[(s)/8] << ((s)%8)) & 0xFF) | (k[(s)/8+1] >> (8-(s)%8)))
217
218 /* DES utils */
219 /* Set up a key schedule based on a 56bit key */
220 static void
221 setup_schedule (const guchar *key_56, DES_KS ks)
222 {
223         guchar key[8];
224         int i, c, bit;
225
226         for (i = 0; i < 8; i++) {
227                 key [i] = KEYBITS (key_56, i * 7);
228
229                 /* Fix parity */
230                 for (c = bit = 0; bit < 8; bit++)
231                         if (key [i] & (1 << bit))
232                                 c++;
233                 if (!(c & 1))
234                         key [i] ^= 0x01;
235         }
236
237         deskey (ks, key, 0);
238 }
239
240 static void
241 ntlm_calc_response (const guchar key[21], const guchar plaintext[8],
242                     guchar results[24])
243 {
244         DES_KS ks;
245
246         memcpy (results, plaintext, 8);
247         memcpy (results + 8, plaintext, 8);
248         memcpy (results + 16, plaintext, 8);
249
250         setup_schedule (key, ks);
251         des (ks, results);
252
253         setup_schedule (key + 7, ks);
254         des (ks, results + 8);
255
256         setup_schedule (key + 14, ks);
257         des (ks, results + 16);
258 }
259
260
261 /* 
262  * MD4 encoder. (The one everyone else uses is not GPL-compatible;
263  * this is a reimplementation from spec.) This doesn't need to be
264  * efficient for our purposes, although it would be nice to fix
265  * it to not malloc()...
266  */
267
268 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
269 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
270 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
271 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
272
273 static void
274 md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
275 {
276         unsigned char *M;
277         guint32 A, B, C, D, AA, BB, CC, DD, X[16];
278         int pbytes, nbits = nbytes * 8, i, j;
279
280         pbytes = (120 - (nbytes % 64)) % 64;
281         M = alloca (nbytes + pbytes + 8);
282         memcpy (M, in, nbytes);
283         memset (M + nbytes, 0, pbytes + 8);
284         M[nbytes] = 0x80;
285         M[nbytes + pbytes] = nbits & 0xFF;
286         M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF;
287         M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF;
288         M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF;
289
290         A = 0x67452301;
291         B = 0xEFCDAB89;
292         C = 0x98BADCFE;
293         D = 0x10325476;
294
295         for (i = 0; i < nbytes + pbytes + 8; i += 64) {
296                 for (j = 0; j < 16; j++) {
297                         X[j] =  (M[i + j*4]) |
298                                 (M[i + j*4 + 1] << 8) |
299                                 (M[i + j*4 + 2] << 16) |
300                                 (M[i + j*4 + 3] << 24);
301                 }
302
303                 AA = A;
304                 BB = B;
305                 CC = C;
306                 DD = D;
307
308                 A = ROT (A + F(B, C, D) + X[0], 3);
309                 D = ROT (D + F(A, B, C) + X[1], 7);
310                 C = ROT (C + F(D, A, B) + X[2], 11);
311                 B = ROT (B + F(C, D, A) + X[3], 19);
312                 A = ROT (A + F(B, C, D) + X[4], 3);
313                 D = ROT (D + F(A, B, C) + X[5], 7);
314                 C = ROT (C + F(D, A, B) + X[6], 11);
315                 B = ROT (B + F(C, D, A) + X[7], 19);
316                 A = ROT (A + F(B, C, D) + X[8], 3);
317                 D = ROT (D + F(A, B, C) + X[9], 7);
318                 C = ROT (C + F(D, A, B) + X[10], 11);
319                 B = ROT (B + F(C, D, A) + X[11], 19);
320                 A = ROT (A + F(B, C, D) + X[12], 3);
321                 D = ROT (D + F(A, B, C) + X[13], 7);
322                 C = ROT (C + F(D, A, B) + X[14], 11);
323                 B = ROT (B + F(C, D, A) + X[15], 19);
324
325                 A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3);
326                 D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5);
327                 C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9);
328                 B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
329                 A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3);
330                 D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5);
331                 C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9);
332                 B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
333                 A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3);
334                 D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5);
335                 C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
336                 B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
337                 A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3);
338                 D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5);
339                 C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
340                 B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
341
342                 A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3);
343                 D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9);
344                 C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11);
345                 B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
346                 A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3);
347                 D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
348                 C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11);
349                 B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
350                 A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3);
351                 D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9);
352                 C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11);
353                 B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
354                 A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3);
355                 D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
356                 C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11);
357                 B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
358
359                 A += AA;
360                 B += BB;
361                 C += CC;
362                 D += DD;
363         }
364
365         digest[0]  =  A        & 0xFF;
366         digest[1]  = (A >>  8) & 0xFF;
367         digest[2]  = (A >> 16) & 0xFF;
368         digest[3]  = (A >> 24) & 0xFF;
369         digest[4]  =  B        & 0xFF;
370         digest[5]  = (B >>  8) & 0xFF;
371         digest[6]  = (B >> 16) & 0xFF;
372         digest[7]  = (B >> 24) & 0xFF;
373         digest[8]  =  C        & 0xFF;
374         digest[9]  = (C >>  8) & 0xFF;
375         digest[10] = (C >> 16) & 0xFF;
376         digest[11] = (C >> 24) & 0xFF;
377         digest[12] =  D        & 0xFF;
378         digest[13] = (D >>  8) & 0xFF;
379         digest[14] = (D >> 16) & 0xFF;
380         digest[15] = (D >> 24) & 0xFF;
381 }
382
383
384 /* Public domain DES implementation from Phil Karn */
385 static guint32 Spbox[8][64] = {
386         { 0x01010400, 0x00000000, 0x00010000, 0x01010404,
387           0x01010004, 0x00010404, 0x00000004, 0x00010000,
388           0x00000400, 0x01010400, 0x01010404, 0x00000400,
389           0x01000404, 0x01010004, 0x01000000, 0x00000004,
390           0x00000404, 0x01000400, 0x01000400, 0x00010400,
391           0x00010400, 0x01010000, 0x01010000, 0x01000404,
392           0x00010004, 0x01000004, 0x01000004, 0x00010004,
393           0x00000000, 0x00000404, 0x00010404, 0x01000000,
394           0x00010000, 0x01010404, 0x00000004, 0x01010000,
395           0x01010400, 0x01000000, 0x01000000, 0x00000400,
396           0x01010004, 0x00010000, 0x00010400, 0x01000004,
397           0x00000400, 0x00000004, 0x01000404, 0x00010404,
398           0x01010404, 0x00010004, 0x01010000, 0x01000404,
399           0x01000004, 0x00000404, 0x00010404, 0x01010400,
400           0x00000404, 0x01000400, 0x01000400, 0x00000000,
401           0x00010004, 0x00010400, 0x00000000, 0x01010004 },
402         { 0x80108020, 0x80008000, 0x00008000, 0x00108020,
403           0x00100000, 0x00000020, 0x80100020, 0x80008020,
404           0x80000020, 0x80108020, 0x80108000, 0x80000000,
405           0x80008000, 0x00100000, 0x00000020, 0x80100020,
406           0x00108000, 0x00100020, 0x80008020, 0x00000000,
407           0x80000000, 0x00008000, 0x00108020, 0x80100000,
408           0x00100020, 0x80000020, 0x00000000, 0x00108000,
409           0x00008020, 0x80108000, 0x80100000, 0x00008020,
410           0x00000000, 0x00108020, 0x80100020, 0x00100000,
411           0x80008020, 0x80100000, 0x80108000, 0x00008000,
412           0x80100000, 0x80008000, 0x00000020, 0x80108020,
413           0x00108020, 0x00000020, 0x00008000, 0x80000000,
414           0x00008020, 0x80108000, 0x00100000, 0x80000020,
415           0x00100020, 0x80008020, 0x80000020, 0x00100020,
416           0x00108000, 0x00000000, 0x80008000, 0x00008020,
417           0x80000000, 0x80100020, 0x80108020, 0x00108000 },
418         { 0x00000208, 0x08020200, 0x00000000, 0x08020008,
419           0x08000200, 0x00000000, 0x00020208, 0x08000200,
420           0x00020008, 0x08000008, 0x08000008, 0x00020000,
421           0x08020208, 0x00020008, 0x08020000, 0x00000208,
422           0x08000000, 0x00000008, 0x08020200, 0x00000200,
423           0x00020200, 0x08020000, 0x08020008, 0x00020208,
424           0x08000208, 0x00020200, 0x00020000, 0x08000208,
425           0x00000008, 0x08020208, 0x00000200, 0x08000000,
426           0x08020200, 0x08000000, 0x00020008, 0x00000208,
427           0x00020000, 0x08020200, 0x08000200, 0x00000000,
428           0x00000200, 0x00020008, 0x08020208, 0x08000200,
429           0x08000008, 0x00000200, 0x00000000, 0x08020008,
430           0x08000208, 0x00020000, 0x08000000, 0x08020208,
431           0x00000008, 0x00020208, 0x00020200, 0x08000008,
432           0x08020000, 0x08000208, 0x00000208, 0x08020000,
433           0x00020208, 0x00000008, 0x08020008, 0x00020200 },
434         { 0x00802001, 0x00002081, 0x00002081, 0x00000080,
435           0x00802080, 0x00800081, 0x00800001, 0x00002001,
436           0x00000000, 0x00802000, 0x00802000, 0x00802081,
437           0x00000081, 0x00000000, 0x00800080, 0x00800001,
438           0x00000001, 0x00002000, 0x00800000, 0x00802001,
439           0x00000080, 0x00800000, 0x00002001, 0x00002080,
440           0x00800081, 0x00000001, 0x00002080, 0x00800080,
441           0x00002000, 0x00802080, 0x00802081, 0x00000081,
442           0x00800080, 0x00800001, 0x00802000, 0x00802081,
443           0x00000081, 0x00000000, 0x00000000, 0x00802000,
444           0x00002080, 0x00800080, 0x00800081, 0x00000001,
445           0x00802001, 0x00002081, 0x00002081, 0x00000080,
446           0x00802081, 0x00000081, 0x00000001, 0x00002000,
447           0x00800001, 0x00002001, 0x00802080, 0x00800081,
448           0x00002001, 0x00002080, 0x00800000, 0x00802001,
449           0x00000080, 0x00800000, 0x00002000, 0x00802080 },
450         { 0x00000100, 0x02080100, 0x02080000, 0x42000100,
451           0x00080000, 0x00000100, 0x40000000, 0x02080000,
452           0x40080100, 0x00080000, 0x02000100, 0x40080100,
453           0x42000100, 0x42080000, 0x00080100, 0x40000000,
454           0x02000000, 0x40080000, 0x40080000, 0x00000000,
455           0x40000100, 0x42080100, 0x42080100, 0x02000100,
456           0x42080000, 0x40000100, 0x00000000, 0x42000000,
457           0x02080100, 0x02000000, 0x42000000, 0x00080100,
458           0x00080000, 0x42000100, 0x00000100, 0x02000000,
459           0x40000000, 0x02080000, 0x42000100, 0x40080100,
460           0x02000100, 0x40000000, 0x42080000, 0x02080100,
461           0x40080100, 0x00000100, 0x02000000, 0x42080000,
462           0x42080100, 0x00080100, 0x42000000, 0x42080100,
463           0x02080000, 0x00000000, 0x40080000, 0x42000000,
464           0x00080100, 0x02000100, 0x40000100, 0x00080000,
465           0x00000000, 0x40080000, 0x02080100, 0x40000100 },
466         { 0x20000010, 0x20400000, 0x00004000, 0x20404010,
467           0x20400000, 0x00000010, 0x20404010, 0x00400000,
468           0x20004000, 0x00404010, 0x00400000, 0x20000010,
469           0x00400010, 0x20004000, 0x20000000, 0x00004010,
470           0x00000000, 0x00400010, 0x20004010, 0x00004000,
471           0x00404000, 0x20004010, 0x00000010, 0x20400010,
472           0x20400010, 0x00000000, 0x00404010, 0x20404000,
473           0x00004010, 0x00404000, 0x20404000, 0x20000000,
474           0x20004000, 0x00000010, 0x20400010, 0x00404000,
475           0x20404010, 0x00400000, 0x00004010, 0x20000010,
476           0x00400000, 0x20004000, 0x20000000, 0x00004010,
477           0x20000010, 0x20404010, 0x00404000, 0x20400000,
478           0x00404010, 0x20404000, 0x00000000, 0x20400010,
479           0x00000010, 0x00004000, 0x20400000, 0x00404010,
480           0x00004000, 0x00400010, 0x20004010, 0x00000000,
481           0x20404000, 0x20000000, 0x00400010, 0x20004010 },
482         { 0x00200000, 0x04200002, 0x04000802, 0x00000000,
483           0x00000800, 0x04000802, 0x00200802, 0x04200800,
484           0x04200802, 0x00200000, 0x00000000, 0x04000002,
485           0x00000002, 0x04000000, 0x04200002, 0x00000802,
486           0x04000800, 0x00200802, 0x00200002, 0x04000800,
487           0x04000002, 0x04200000, 0x04200800, 0x00200002,
488           0x04200000, 0x00000800, 0x00000802, 0x04200802,
489           0x00200800, 0x00000002, 0x04000000, 0x00200800,
490           0x04000000, 0x00200800, 0x00200000, 0x04000802,
491           0x04000802, 0x04200002, 0x04200002, 0x00000002,
492           0x00200002, 0x04000000, 0x04000800, 0x00200000,
493           0x04200800, 0x00000802, 0x00200802, 0x04200800,
494           0x00000802, 0x04000002, 0x04200802, 0x04200000,
495           0x00200800, 0x00000000, 0x00000002, 0x04200802,
496           0x00000000, 0x00200802, 0x04200000, 0x00000800,
497           0x04000002, 0x04000800, 0x00000800, 0x00200002 },
498         { 0x10001040, 0x00001000, 0x00040000, 0x10041040,
499           0x10000000, 0x10001040, 0x00000040, 0x10000000,
500           0x00040040, 0x10040000, 0x10041040, 0x00041000,
501           0x10041000, 0x00041040, 0x00001000, 0x00000040,
502           0x10040000, 0x10000040, 0x10001000, 0x00001040,
503           0x00041000, 0x00040040, 0x10040040, 0x10041000,
504           0x00001040, 0x00000000, 0x00000000, 0x10040040,
505           0x10000040, 0x10001000, 0x00041040, 0x00040000,
506           0x00041040, 0x00040000, 0x10041000, 0x00001000,
507           0x00000040, 0x10040040, 0x00001000, 0x00041040,
508           0x10001000, 0x00000040, 0x10000040, 0x10040000,
509           0x10040040, 0x10000000, 0x00040000, 0x10001040,
510           0x00000000, 0x10041040, 0x00040040, 0x10000040,
511           0x10040000, 0x10001000, 0x10001040, 0x00000000,
512           0x10041040, 0x00041000, 0x00041000, 0x00001040,
513           0x00001040, 0x00040040, 0x10000000, 0x10041000 }
514 };
515
516 #undef F
517 #define F(l,r,key){\
518         work = ((r >> 4) | (r << 28)) ^ key[0];\
519         l ^= Spbox[6][work & 0x3f];\
520         l ^= Spbox[4][(work >> 8) & 0x3f];\
521         l ^= Spbox[2][(work >> 16) & 0x3f];\
522         l ^= Spbox[0][(work >> 24) & 0x3f];\
523         work = r ^ key[1];\
524         l ^= Spbox[7][work & 0x3f];\
525         l ^= Spbox[5][(work >> 8) & 0x3f];\
526         l ^= Spbox[3][(work >> 16) & 0x3f];\
527         l ^= Spbox[1][(work >> 24) & 0x3f];\
528 }
529
530 /* Encrypt or decrypt a block of data in ECB mode */
531 static void
532 des (guint32 ks[16][2], unsigned char block[8])
533 {
534         guint32 left, right, work;
535         
536         /* Read input block and place in left/right in big-endian order */
537         left = ((guint32)block[0] << 24)
538          | ((guint32)block[1] << 16)
539          | ((guint32)block[2] << 8)
540          | (guint32)block[3];
541         right = ((guint32)block[4] << 24)
542          | ((guint32)block[5] << 16)
543          | ((guint32)block[6] << 8)
544          | (guint32)block[7];
545
546         /* Hoey's clever initial permutation algorithm, from Outerbridge
547          * (see Schneier p 478) 
548          *
549          * The convention here is the same as Outerbridge: rotate each
550          * register left by 1 bit, i.e., so that "left" contains permuted
551          * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32    
552          * (using origin-1 numbering as in the FIPS). This allows us to avoid
553          * one of the two rotates that would otherwise be required in each of
554          * the 16 rounds.
555          */
556         work = ((left >> 4) ^ right) & 0x0f0f0f0f;
557         right ^= work;
558         left ^= work << 4;
559         work = ((left >> 16) ^ right) & 0xffff;
560         right ^= work;
561         left ^= work << 16;
562         work = ((right >> 2) ^ left) & 0x33333333;
563         left ^= work;
564         right ^= (work << 2);
565         work = ((right >> 8) ^ left) & 0xff00ff;
566         left ^= work;
567         right ^= (work << 8);
568         right = (right << 1) | (right >> 31);
569         work = (left ^ right) & 0xaaaaaaaa;
570         left ^= work;
571         right ^= work;
572         left = (left << 1) | (left >> 31);
573
574         /* Now do the 16 rounds */
575         F(left,right,ks[0]);
576         F(right,left,ks[1]);
577         F(left,right,ks[2]);
578         F(right,left,ks[3]);
579         F(left,right,ks[4]);
580         F(right,left,ks[5]);
581         F(left,right,ks[6]);
582         F(right,left,ks[7]);
583         F(left,right,ks[8]);
584         F(right,left,ks[9]);
585         F(left,right,ks[10]);
586         F(right,left,ks[11]);
587         F(left,right,ks[12]);
588         F(right,left,ks[13]);
589         F(left,right,ks[14]);
590         F(right,left,ks[15]);
591
592         /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
593         right = (right << 31) | (right >> 1);
594         work = (left ^ right) & 0xaaaaaaaa;
595         left ^= work;
596         right ^= work;
597         left = (left >> 1) | (left  << 31);
598         work = ((left >> 8) ^ right) & 0xff00ff;
599         right ^= work;
600         left ^= work << 8;
601         work = ((left >> 2) ^ right) & 0x33333333;
602         right ^= work;
603         left ^= work << 2;
604         work = ((right >> 16) ^ left) & 0xffff;
605         left ^= work;
606         right ^= work << 16;
607         work = ((right >> 4) ^ left) & 0x0f0f0f0f;
608         left ^= work;
609         right ^= work << 4;
610
611         /* Put the block back into the user's buffer with final swap */
612         block[0] = right >> 24;
613         block[1] = right >> 16;
614         block[2] = right >> 8;
615         block[3] = right;
616         block[4] = left >> 24;
617         block[5] = left >> 16;
618         block[6] = left >> 8;
619         block[7] = left;
620 }
621
622 /* Key schedule-related tables from FIPS-46 */
623
624 /* permuted choice table (key) */
625 static unsigned char pc1[] = {
626         57, 49, 41, 33, 25, 17,  9,
627          1, 58, 50, 42, 34, 26, 18,
628         10,  2, 59, 51, 43, 35, 27,
629         19, 11,  3, 60, 52, 44, 36,
630
631         63, 55, 47, 39, 31, 23, 15,
632          7, 62, 54, 46, 38, 30, 22,
633         14,  6, 61, 53, 45, 37, 29,
634         21, 13,  5, 28, 20, 12,  4
635 };
636
637 /* number left rotations of pc1 */
638 static unsigned char totrot[] = {
639         1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
640 };
641
642 /* permuted choice key (table) */
643 static unsigned char pc2[] = {
644         14, 17, 11, 24,  1,  5,
645          3, 28, 15,  6, 21, 10,
646         23, 19, 12,  4, 26,  8,
647         16,  7, 27, 20, 13,  2,
648         41, 52, 31, 37, 47, 55,
649         30, 40, 51, 45, 33, 48,
650         44, 49, 39, 56, 34, 53,
651         46, 42, 50, 36, 29, 32
652 };
653
654 /* End of DES-defined tables */
655
656
657 /* bit 0 is left-most in byte */
658 static int bytebit[] = {
659         0200,0100,040,020,010,04,02,01
660 };
661
662
663 /* Generate key schedule for encryption or decryption
664  * depending on the value of "decrypt"
665  */
666 static void
667 deskey (DES_KS k, unsigned char *key, int decrypt)
668 {
669         unsigned char pc1m[56];         /* place to modify pc1 into */
670         unsigned char pcr[56];          /* place to rotate pc1 into */
671         register int i,j,l;
672         int m;
673         unsigned char ks[8];
674
675         for (j=0; j<56; j++) {          /* convert pc1 to bits of key */
676                 l=pc1[j]-1;             /* integer bit location  */
677                 m = l & 07;             /* find bit              */
678                 pc1m[j]=(key[l>>3] &    /* find which key byte l is in */
679                         bytebit[m])     /* and which bit of that byte */
680                         ? 1 : 0;        /* and store 1-bit result */
681         }
682         for (i=0; i<16; i++) {          /* key chunk for each iteration */
683                 memset(ks,0,sizeof(ks));        /* Clear key schedule */
684                 for (j=0; j<56; j++)    /* rotate pc1 the right amount */
685                         pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28];
686                         /* rotate left and right halves independently */
687                 for (j=0; j<48; j++){   /* select bits individually */
688                         /* check bit that goes to ks[j] */
689                         if (pcr[pc2[j]-1]){
690                                 /* mask it in if it's there */
691                                 l= j % 6;
692                                 ks[j/6] |= bytebit[l] >> 2;
693                         }
694                 }
695                 /* Now convert to packed odd/even interleaved form */
696                 k[i][0] = ((guint32)ks[0] << 24)
697                  | ((guint32)ks[2] << 16)
698                  | ((guint32)ks[4] << 8)
699                  | ((guint32)ks[6]);
700                 k[i][1] = ((guint32)ks[1] << 24)
701                  | ((guint32)ks[3] << 16)
702                  | ((guint32)ks[5] << 8)
703                  | ((guint32)ks[7]);
704         }
705 }