Define two new signals, request_queued and request_unqueued, to provided a
[platform/upstream/libsoup.git] / libsoup / soup-auth-manager-ntlm.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-auth-manager-ntlm.c: NTLM auth manager
4  *
5  * Copyright (C) 2001-2007 Novell, Inc.
6  * Copyright (C) 2008 Red Hat, Inc.
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <ctype.h>
14 #include <string.h>
15
16 #include "soup-auth-manager-ntlm.h"
17 #include "soup-auth-ntlm.h"
18 #include "soup-message.h"
19 #include "soup-message-private.h"
20 #include "soup-misc.h"
21 #include "soup-session.h"
22 #include "soup-session-private.h"
23 #include "soup-uri.h"
24
25 typedef enum {
26         SOUP_NTLM_NEW,
27         SOUP_NTLM_SENT_REQUEST,
28         SOUP_NTLM_RECEIVED_CHALLENGE,
29         SOUP_NTLM_SENT_RESPONSE,
30         SOUP_NTLM_FAILED
31 } SoupNTLMState;
32
33 typedef struct {
34         SoupSocket *socket;
35         SoupNTLMState state;
36         char *response_header;
37
38         char *nonce, *domain;
39         SoupAuth *auth;
40 } SoupNTLMConnection;
41
42 struct SoupAuthManagerNTLM {
43         SoupSession *session;
44         GHashTable *connections_by_msg;
45         GHashTable *connections_by_id;
46 };
47
48 static void ntlm_request_queued (SoupSession *session, SoupMessage *msg,
49                                  gpointer ntlm);
50 static void ntlm_request_started (SoupSession *session, SoupMessage *msg,
51                                   SoupSocket *socket, gpointer ntlm);
52 static void ntlm_request_unqueued (SoupSession *session, SoupMessage *msg,
53                                    gpointer ntlm);
54
55 static char     *soup_ntlm_request         (void);
56 static gboolean  soup_ntlm_parse_challenge (const char  *challenge,
57                                             char       **nonce,
58                                             char       **default_domain);
59 static char     *soup_ntlm_response        (const char  *nonce, 
60                                             const char  *user,
61                                             const char  *password,
62                                             const char  *host, 
63                                             const char  *domain);
64
65 SoupAuthManagerNTLM *
66 soup_auth_manager_ntlm_new (SoupSession *session)
67 {
68         SoupAuthManagerNTLM *ntlm;
69
70         ntlm = g_slice_new (SoupAuthManagerNTLM);
71         ntlm->session = session;
72         ntlm->connections_by_id = g_hash_table_new (NULL, NULL);
73         ntlm->connections_by_msg = g_hash_table_new (NULL, NULL);
74         g_signal_connect (session, "request_queued",
75                           G_CALLBACK (ntlm_request_queued), ntlm);
76         g_signal_connect (session, "request_started",
77                           G_CALLBACK (ntlm_request_started), ntlm);
78         g_signal_connect (session, "request_unqueued",
79                           G_CALLBACK (ntlm_request_unqueued), ntlm);
80         return ntlm;
81 }
82
83 static void
84 free_ntlm_connection (SoupNTLMConnection *conn)
85 {
86         g_free (conn->response_header);
87         g_free (conn->nonce);
88         g_free (conn->domain);
89         if (conn->auth)
90                 g_object_unref (conn->auth);
91         g_slice_free (SoupNTLMConnection, conn);
92 }
93
94 static void
95 free_ntlm_connection_foreach (gpointer key, gpointer value, gpointer user_data)
96 {
97         free_ntlm_connection (value);
98 }
99
100 void
101 soup_auth_manager_ntlm_free (SoupAuthManagerNTLM *ntlm)
102 {
103         g_hash_table_foreach (ntlm->connections_by_id,
104                               free_ntlm_connection_foreach, NULL);
105         g_hash_table_destroy (ntlm->connections_by_id);
106         g_hash_table_destroy (ntlm->connections_by_msg);
107         g_signal_handlers_disconnect_by_func (ntlm->session,
108                                               ntlm_request_queued, ntlm);
109         g_signal_handlers_disconnect_by_func (ntlm->session,
110                                               ntlm_request_started, ntlm);
111         g_signal_handlers_disconnect_by_func (ntlm->session,
112                                               ntlm_request_unqueued, ntlm);
113
114         g_slice_free (SoupAuthManagerNTLM, ntlm);
115 }
116
117 static void
118 delete_conn (SoupSocket *socket, gpointer user_data)
119 {
120         SoupAuthManagerNTLM *ntlm = user_data;
121         SoupNTLMConnection *conn;
122
123         conn = g_hash_table_lookup (ntlm->connections_by_id, socket);
124         if (conn)
125                 free_ntlm_connection (conn);
126         g_hash_table_remove (ntlm->connections_by_id, socket);
127         g_signal_handlers_disconnect_by_func (socket, delete_conn, ntlm);
128 }
129
130 static SoupNTLMConnection *
131 get_connection (SoupAuthManagerNTLM *ntlm, SoupSocket *socket)
132 {
133         SoupNTLMConnection *conn;
134
135         conn = g_hash_table_lookup (ntlm->connections_by_id, socket);
136         if (conn)
137                 return conn;
138
139         conn = g_slice_new0 (SoupNTLMConnection);
140         conn->socket = socket;
141         conn->state = SOUP_NTLM_NEW;
142         g_hash_table_insert (ntlm->connections_by_id, socket, conn);
143
144         g_signal_connect (socket, "disconnected",
145                           G_CALLBACK (delete_conn), ntlm);
146         return conn;
147 }
148
149 static void
150 unset_conn (SoupMessage *msg, gpointer user_data)
151 {
152         SoupAuthManagerNTLM *ntlm = user_data;
153
154         g_hash_table_remove (ntlm->connections_by_msg, msg);
155         g_signal_handlers_disconnect_by_func (msg, unset_conn, ntlm);
156 }
157
158 static SoupNTLMConnection *
159 set_connection_for_msg (SoupAuthManagerNTLM *ntlm, SoupMessage *msg,
160                         SoupNTLMConnection *conn)
161 {
162         if (!g_hash_table_lookup (ntlm->connections_by_msg, msg)) {
163                 g_signal_connect (msg, "finished",
164                                   G_CALLBACK (unset_conn), ntlm);
165                 g_signal_connect (msg, "restarted",
166                                   G_CALLBACK (unset_conn), ntlm);
167         }
168         g_hash_table_insert (ntlm->connections_by_msg, msg, conn);
169
170         return conn;
171 }
172
173 static SoupNTLMConnection *
174 get_connection_for_msg (SoupAuthManagerNTLM *ntlm, SoupMessage *msg)
175 {
176         return g_hash_table_lookup (ntlm->connections_by_msg, msg);
177 }
178
179 static void
180 ntlm_authorize_pre (SoupMessage *msg, gpointer user_data)
181 {
182         SoupAuthManagerNTLM *ntlm = user_data;
183         SoupNTLMConnection *conn;
184         const char *val;
185
186         conn = get_connection_for_msg (ntlm, msg);
187         if (!conn)
188                 return;
189
190         if (conn->state > SOUP_NTLM_SENT_REQUEST) {
191                 /* We already authenticated, but then got another 401.
192                  * That means "permission denied", so don't try to
193                  * authenticate again.
194                  */
195                 conn->state = SOUP_NTLM_FAILED;
196                 goto done;
197         }
198
199         val = soup_message_headers_get (msg->response_headers,
200                                         "WWW-Authenticate");
201         if (val)
202                 val = strstr (val, "NTLM ");
203         if (!val) {
204                 conn->state = SOUP_NTLM_FAILED;
205                 goto done;
206         }
207
208         if (!soup_ntlm_parse_challenge (val, &conn->nonce, &conn->domain)) {
209                 conn->state = SOUP_NTLM_FAILED;
210                 goto done;
211         }
212
213         conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
214         conn->auth = soup_auth_ntlm_new (conn->domain,
215                                          soup_message_get_uri (msg)->host);
216         soup_session_emit_authenticate (ntlm->session, msg, conn->auth, FALSE);
217
218  done:
219         /* Remove the WWW-Authenticate headers so the session won't try
220          * to do Basic auth too.
221          */
222         soup_message_headers_remove (msg->response_headers, "WWW-Authenticate");
223 }
224
225 static void
226 ntlm_authorize_post (SoupMessage *msg, gpointer user_data)
227 {
228         SoupAuthManagerNTLM *ntlm = user_data;
229         SoupNTLMConnection *conn;
230         const char *username = NULL, *password = NULL;
231         char *slash, *domain;
232
233         conn = get_connection_for_msg (ntlm, msg);
234         if (!conn || !conn->auth)
235                 return;
236
237         username = soup_auth_ntlm_get_username (conn->auth);
238         password = soup_auth_ntlm_get_password (conn->auth);
239         if (!username || !password)
240                 goto done;
241
242         slash = strpbrk (username, "\\/");
243         if (slash) {
244                 domain = g_strdup (username);
245                 slash = domain + (slash - username);
246                 *slash = '\0';
247                 username = slash + 1;
248         } else
249                 domain = conn->domain;
250
251         conn->response_header = soup_ntlm_response (conn->nonce,
252                                                     username, password,
253                                                     NULL, domain);
254         soup_session_requeue_message (ntlm->session, msg);
255
256 done:
257         if (domain != conn->domain)
258                 g_free (domain);
259         g_free (conn->domain);
260         conn->domain = NULL;
261         g_free (conn->nonce);
262         conn->nonce = NULL;
263         g_object_unref (conn->auth);
264         conn->auth = NULL;
265 }
266
267 static void
268 ntlm_request_queued (SoupSession *session, SoupMessage *msg, gpointer ntlm)
269 {
270         soup_message_add_status_code_handler (msg, "got_headers",
271                                               SOUP_STATUS_UNAUTHORIZED,
272                                               G_CALLBACK (ntlm_authorize_pre),
273                                               ntlm);
274         soup_message_add_status_code_handler (msg, "got_body",
275                                               SOUP_STATUS_UNAUTHORIZED,
276                                               G_CALLBACK (ntlm_authorize_post),
277                                               ntlm);
278 }
279
280 static void
281 ntlm_request_started (SoupSession *session, SoupMessage *msg,
282                       SoupSocket *socket, gpointer user_data)
283 {
284         SoupAuthManagerNTLM *ntlm = user_data;
285         SoupNTLMConnection *conn;
286         char *header = NULL;
287
288         conn = get_connection (ntlm, socket);
289         set_connection_for_msg (ntlm, msg, conn);
290
291         switch (conn->state) {
292         case SOUP_NTLM_NEW:
293                 header = soup_ntlm_request ();
294                 conn->state = SOUP_NTLM_SENT_REQUEST;
295                 break;
296         case SOUP_NTLM_RECEIVED_CHALLENGE:
297                 header = conn->response_header;
298                 conn->response_header = NULL;
299                 conn->state = SOUP_NTLM_SENT_RESPONSE;
300                 break;
301         default:
302                 break;
303         }
304
305         if (header && !soup_message_get_auth (msg)) {
306                 soup_message_headers_replace (msg->request_headers,
307                                               "Authorization", header);
308                 g_free (header);
309         }
310 }
311
312 static void
313 ntlm_request_unqueued (SoupSession *session, SoupMessage *msg,
314                        gpointer ntlm)
315 {
316         g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_pre, ntlm);
317         g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_post, ntlm);
318 }
319
320
321 /* NTLM code */
322
323 static void md4sum                (const unsigned char *in, 
324                                    int                  nbytes, 
325                                    unsigned char        digest[16]);
326
327 typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */
328
329 static void deskey                (DES_KS, unsigned char *, int);
330
331 static void des                   (DES_KS, unsigned char *);
332
333 static void setup_schedule        (const guchar *key_56, DES_KS ks);
334
335 static void calc_response         (const guchar        *key, 
336                                    const guchar        *plaintext,
337                                    guchar              *results);
338
339 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
340                           "\x4B\x47\x53\x21\x40\x23\x24\x25" \
341                           "\x00\x00\x00\x00\x00"
342
343 static void
344 lanmanager_hash (const char *password, guchar hash[21])
345 {
346         guchar lm_password [15];
347         DES_KS ks;
348         int i;
349
350         for (i = 0; i < 14 && password [i]; i++)
351                 lm_password [i] = toupper ((unsigned char) password [i]);
352
353         for (; i < 15; i++)
354                 lm_password [i] = '\0';
355
356         memcpy (hash, LM_PASSWORD_MAGIC, 21);
357
358         setup_schedule (lm_password, ks);
359         des (ks, hash);
360
361         setup_schedule (lm_password + 7, ks);
362         des (ks, hash + 8);
363 }
364
365 static void
366 nt_hash (const char *password, guchar hash[21])
367 {
368         unsigned char *buf, *p;
369
370         p = buf = g_malloc (strlen (password) * 2);
371
372         while (*password) {
373                 *p++ = *password++;
374                 *p++ = '\0';
375         }
376
377         md4sum (buf, p - buf, hash);
378         memset (hash + 16, 0, 5);
379
380         g_free (buf);
381 }
382
383 typedef struct {
384         guint16 length;
385         guint16 length2;
386         guint16 offset;
387         guchar  zero_pad[2];
388 } NTLMString;
389
390 #define NTLM_CHALLENGE_NONCE_OFFSET         24
391 #define NTLM_CHALLENGE_NONCE_LENGTH          8
392 #define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
393
394 #define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
395 #define NTLM_RESPONSE_FLAGS 0x8202
396
397 typedef struct {
398         guchar     header[12];
399
400         NTLMString lm_resp;
401         NTLMString nt_resp;
402         NTLMString domain;
403         NTLMString user;
404         NTLMString host;
405         NTLMString session_key;
406
407         guint32    flags;
408 } NTLMResponse;
409
410 static void
411 ntlm_set_string (NTLMString *string, int *offset, int len)
412 {
413         string->offset = GUINT16_TO_LE (*offset);
414         string->length = string->length2 = GUINT16_TO_LE (len);
415         *offset += len;
416 }
417
418 static char *
419 soup_ntlm_request (void)
420 {
421         return g_strdup ("NTLM TlRMTVNTUAABAAAABoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
422 }
423
424 static gboolean
425 soup_ntlm_parse_challenge (const char *challenge,
426                            char      **nonce,
427                            char      **default_domain)
428 {
429         gsize clen;
430         NTLMString domain;
431         guchar *chall;
432
433         if (strncmp (challenge, "NTLM ", 5) != 0)
434                 return FALSE;
435
436         chall = g_base64_decode (challenge + 5, &clen);
437         if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET ||
438             clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) {
439                 g_free (chall);
440                 return FALSE;
441         }
442
443         if (default_domain) {
444                 memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain));
445                 domain.length = GUINT16_FROM_LE (domain.length);
446                 domain.offset = GUINT16_FROM_LE (domain.offset);
447
448                 if (clen < domain.length + domain.offset) {
449                         g_free (chall);
450                         return FALSE;
451                 }
452
453                 *default_domain = g_strndup ((char *)chall + domain.offset, domain.length);
454         }
455
456         if (nonce) {
457                 *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET,
458                                    NTLM_CHALLENGE_NONCE_LENGTH);
459         }
460
461         g_free (chall);
462         return TRUE;
463 }
464
465 static char *
466 soup_ntlm_response (const char *nonce, 
467                     const char *user,
468                     const char *password,
469                     const char *host, 
470                     const char *domain)
471 {
472         int hlen, dlen, ulen, offset;
473         guchar hash[21], lm_resp[24], nt_resp[24];
474         NTLMResponse resp;
475         char *out, *p;
476         int state, save;
477
478         nt_hash (password, hash);
479         calc_response (hash, (guchar *)nonce, nt_resp);
480         lanmanager_hash (password, hash);
481         calc_response (hash, (guchar *)nonce, lm_resp);
482
483         memset (&resp, 0, sizeof (resp));
484         memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header));
485         resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS);
486
487         offset = sizeof (resp);
488
489         dlen = strlen (domain);
490         ntlm_set_string (&resp.domain, &offset, dlen);
491         ulen = strlen (user);
492         ntlm_set_string (&resp.user, &offset, ulen);
493         if (!host)
494                 host = "UNKNOWN";
495         hlen = strlen (host);
496         ntlm_set_string (&resp.host, &offset, hlen);
497         ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp));
498         ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp));
499
500         out = g_malloc (((offset + 3) * 4) / 3 + 6);
501         strncpy (out, "NTLM ", 5);
502         p = out + 5;
503
504         state = save = 0;
505
506         p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp), 
507                                    FALSE, p, &state, &save);
508         p += g_base64_encode_step ((const guchar *) domain, dlen, 
509                                    FALSE, p, &state, &save);
510         p += g_base64_encode_step ((const guchar *) user, ulen, 
511                                    FALSE, p, &state, &save);
512         p += g_base64_encode_step ((const guchar *) host, hlen, 
513                                    FALSE, p, &state, &save);
514         p += g_base64_encode_step (lm_resp, sizeof (lm_resp), 
515                                    FALSE, p, &state, &save);
516         p += g_base64_encode_step (nt_resp, sizeof (nt_resp), 
517                                    FALSE, p, &state, &save);
518         p += g_base64_encode_close (FALSE, p, &state, &save);
519         *p = '\0';
520
521         return out;
522 }
523
524 /* DES utils */
525 /* Set up a key schedule based on a 56bit key */
526 static void
527 setup_schedule (const guchar *key_56, DES_KS ks)
528 {
529         guchar key[8];
530         int i, c, bit;
531
532         key[0] = (key_56[0])                                 ;
533         key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF);
534         key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF);
535         key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF);
536         key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF);
537         key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF);
538         key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF);
539         key[7] =                    ((key_56[6] << 1) & 0xFF);
540
541         /* Fix parity */
542         for (i = 0; i < 8; i++) {
543                 for (c = bit = 0; bit < 8; bit++)
544                         if (key[i] & (1 << bit))
545                                 c++;
546                 if (!(c & 1))
547                         key[i] ^= 0x01;
548         }
549
550         deskey (ks, key, 0);
551 }
552
553 static void
554 calc_response (const guchar *key, const guchar *plaintext, guchar *results)
555 {
556         DES_KS ks;
557
558         memcpy (results, plaintext, 8);
559         memcpy (results + 8, plaintext, 8);
560         memcpy (results + 16, plaintext, 8);
561
562         setup_schedule (key, ks);
563         des (ks, results);
564
565         setup_schedule (key + 7, ks);
566         des (ks, results + 8);
567
568         setup_schedule (key + 14, ks);
569         des (ks, results + 16);
570 }
571
572
573 /* 
574  * MD4 encoder. (The one everyone else uses is not GPL-compatible;
575  * this is a reimplementation from spec.) This doesn't need to be
576  * efficient for our purposes, although it would be nice to fix
577  * it to not malloc()...
578  */
579
580 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
581 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
582 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
583 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
584
585 static void
586 md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
587 {
588         unsigned char *M;
589         guint32 A, B, C, D, AA, BB, CC, DD, X[16];
590         int pbytes, nbits = nbytes * 8, i, j;
591
592         pbytes = (120 - (nbytes % 64)) % 64;
593         M = alloca (nbytes + pbytes + 8);
594         memcpy (M, in, nbytes);
595         memset (M + nbytes, 0, pbytes + 8);
596         M[nbytes] = 0x80;
597         M[nbytes + pbytes] = nbits & 0xFF;
598         M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF;
599         M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF;
600         M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF;
601
602         A = 0x67452301;
603         B = 0xEFCDAB89;
604         C = 0x98BADCFE;
605         D = 0x10325476;
606
607         for (i = 0; i < nbytes + pbytes + 8; i += 64) {
608                 for (j = 0; j < 16; j++) {
609                         X[j] =  (M[i + j*4]) |
610                                 (M[i + j*4 + 1] << 8) |
611                                 (M[i + j*4 + 2] << 16) |
612                                 (M[i + j*4 + 3] << 24);
613                 }
614
615                 AA = A;
616                 BB = B;
617                 CC = C;
618                 DD = D;
619
620                 A = ROT (A + F(B, C, D) + X[0], 3);
621                 D = ROT (D + F(A, B, C) + X[1], 7);
622                 C = ROT (C + F(D, A, B) + X[2], 11);
623                 B = ROT (B + F(C, D, A) + X[3], 19);
624                 A = ROT (A + F(B, C, D) + X[4], 3);
625                 D = ROT (D + F(A, B, C) + X[5], 7);
626                 C = ROT (C + F(D, A, B) + X[6], 11);
627                 B = ROT (B + F(C, D, A) + X[7], 19);
628                 A = ROT (A + F(B, C, D) + X[8], 3);
629                 D = ROT (D + F(A, B, C) + X[9], 7);
630                 C = ROT (C + F(D, A, B) + X[10], 11);
631                 B = ROT (B + F(C, D, A) + X[11], 19);
632                 A = ROT (A + F(B, C, D) + X[12], 3);
633                 D = ROT (D + F(A, B, C) + X[13], 7);
634                 C = ROT (C + F(D, A, B) + X[14], 11);
635                 B = ROT (B + F(C, D, A) + X[15], 19);
636
637                 A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3);
638                 D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5);
639                 C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9);
640                 B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
641                 A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3);
642                 D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5);
643                 C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9);
644                 B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
645                 A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3);
646                 D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5);
647                 C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
648                 B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
649                 A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3);
650                 D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5);
651                 C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
652                 B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
653
654                 A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3);
655                 D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9);
656                 C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11);
657                 B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
658                 A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3);
659                 D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
660                 C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11);
661                 B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
662                 A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3);
663                 D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9);
664                 C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11);
665                 B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
666                 A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3);
667                 D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
668                 C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11);
669                 B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
670
671                 A += AA;
672                 B += BB;
673                 C += CC;
674                 D += DD;
675         }
676
677         digest[0]  =  A        & 0xFF;
678         digest[1]  = (A >>  8) & 0xFF;
679         digest[2]  = (A >> 16) & 0xFF;
680         digest[3]  = (A >> 24) & 0xFF;
681         digest[4]  =  B        & 0xFF;
682         digest[5]  = (B >>  8) & 0xFF;
683         digest[6]  = (B >> 16) & 0xFF;
684         digest[7]  = (B >> 24) & 0xFF;
685         digest[8]  =  C        & 0xFF;
686         digest[9]  = (C >>  8) & 0xFF;
687         digest[10] = (C >> 16) & 0xFF;
688         digest[11] = (C >> 24) & 0xFF;
689         digest[12] =  D        & 0xFF;
690         digest[13] = (D >>  8) & 0xFF;
691         digest[14] = (D >> 16) & 0xFF;
692         digest[15] = (D >> 24) & 0xFF;
693 }
694
695
696 /* Public domain DES implementation from Phil Karn */
697 static const guint32 Spbox[8][64] = {
698         { 0x01010400,0x00000000,0x00010000,0x01010404,
699           0x01010004,0x00010404,0x00000004,0x00010000,
700           0x00000400,0x01010400,0x01010404,0x00000400,
701           0x01000404,0x01010004,0x01000000,0x00000004,
702           0x00000404,0x01000400,0x01000400,0x00010400,
703           0x00010400,0x01010000,0x01010000,0x01000404,
704           0x00010004,0x01000004,0x01000004,0x00010004,
705           0x00000000,0x00000404,0x00010404,0x01000000,
706           0x00010000,0x01010404,0x00000004,0x01010000,
707           0x01010400,0x01000000,0x01000000,0x00000400,
708           0x01010004,0x00010000,0x00010400,0x01000004,
709           0x00000400,0x00000004,0x01000404,0x00010404,
710           0x01010404,0x00010004,0x01010000,0x01000404,
711           0x01000004,0x00000404,0x00010404,0x01010400,
712           0x00000404,0x01000400,0x01000400,0x00000000,
713           0x00010004,0x00010400,0x00000000,0x01010004 },
714         { 0x80108020,0x80008000,0x00008000,0x00108020,
715           0x00100000,0x00000020,0x80100020,0x80008020,
716           0x80000020,0x80108020,0x80108000,0x80000000,
717           0x80008000,0x00100000,0x00000020,0x80100020,
718           0x00108000,0x00100020,0x80008020,0x00000000,
719           0x80000000,0x00008000,0x00108020,0x80100000,
720           0x00100020,0x80000020,0x00000000,0x00108000,
721           0x00008020,0x80108000,0x80100000,0x00008020,
722           0x00000000,0x00108020,0x80100020,0x00100000,
723           0x80008020,0x80100000,0x80108000,0x00008000,
724           0x80100000,0x80008000,0x00000020,0x80108020,
725           0x00108020,0x00000020,0x00008000,0x80000000,
726           0x00008020,0x80108000,0x00100000,0x80000020,
727           0x00100020,0x80008020,0x80000020,0x00100020,
728           0x00108000,0x00000000,0x80008000,0x00008020,
729           0x80000000,0x80100020,0x80108020,0x00108000 },
730         { 0x00000208,0x08020200,0x00000000,0x08020008,
731           0x08000200,0x00000000,0x00020208,0x08000200,
732           0x00020008,0x08000008,0x08000008,0x00020000,
733           0x08020208,0x00020008,0x08020000,0x00000208,
734           0x08000000,0x00000008,0x08020200,0x00000200,
735           0x00020200,0x08020000,0x08020008,0x00020208,
736           0x08000208,0x00020200,0x00020000,0x08000208,
737           0x00000008,0x08020208,0x00000200,0x08000000,
738           0x08020200,0x08000000,0x00020008,0x00000208,
739           0x00020000,0x08020200,0x08000200,0x00000000,
740           0x00000200,0x00020008,0x08020208,0x08000200,
741           0x08000008,0x00000200,0x00000000,0x08020008,
742           0x08000208,0x00020000,0x08000000,0x08020208,
743           0x00000008,0x00020208,0x00020200,0x08000008,
744           0x08020000,0x08000208,0x00000208,0x08020000,
745           0x00020208,0x00000008,0x08020008,0x00020200 },
746         { 0x00802001,0x00002081,0x00002081,0x00000080,
747           0x00802080,0x00800081,0x00800001,0x00002001,
748           0x00000000,0x00802000,0x00802000,0x00802081,
749           0x00000081,0x00000000,0x00800080,0x00800001,
750           0x00000001,0x00002000,0x00800000,0x00802001,
751           0x00000080,0x00800000,0x00002001,0x00002080,
752           0x00800081,0x00000001,0x00002080,0x00800080,
753           0x00002000,0x00802080,0x00802081,0x00000081,
754           0x00800080,0x00800001,0x00802000,0x00802081,
755           0x00000081,0x00000000,0x00000000,0x00802000,
756           0x00002080,0x00800080,0x00800081,0x00000001,
757           0x00802001,0x00002081,0x00002081,0x00000080,
758           0x00802081,0x00000081,0x00000001,0x00002000,
759           0x00800001,0x00002001,0x00802080,0x00800081,
760           0x00002001,0x00002080,0x00800000,0x00802001,
761           0x00000080,0x00800000,0x00002000,0x00802080 },
762         { 0x00000100,0x02080100,0x02080000,0x42000100,
763           0x00080000,0x00000100,0x40000000,0x02080000,
764           0x40080100,0x00080000,0x02000100,0x40080100,
765           0x42000100,0x42080000,0x00080100,0x40000000,
766           0x02000000,0x40080000,0x40080000,0x00000000,
767           0x40000100,0x42080100,0x42080100,0x02000100,
768           0x42080000,0x40000100,0x00000000,0x42000000,
769           0x02080100,0x02000000,0x42000000,0x00080100,
770           0x00080000,0x42000100,0x00000100,0x02000000,
771           0x40000000,0x02080000,0x42000100,0x40080100,
772           0x02000100,0x40000000,0x42080000,0x02080100,
773           0x40080100,0x00000100,0x02000000,0x42080000,
774           0x42080100,0x00080100,0x42000000,0x42080100,
775           0x02080000,0x00000000,0x40080000,0x42000000,
776           0x00080100,0x02000100,0x40000100,0x00080000,
777           0x00000000,0x40080000,0x02080100,0x40000100 },
778         { 0x20000010,0x20400000,0x00004000,0x20404010,
779           0x20400000,0x00000010,0x20404010,0x00400000,
780           0x20004000,0x00404010,0x00400000,0x20000010,
781           0x00400010,0x20004000,0x20000000,0x00004010,
782           0x00000000,0x00400010,0x20004010,0x00004000,
783           0x00404000,0x20004010,0x00000010,0x20400010,
784           0x20400010,0x00000000,0x00404010,0x20404000,
785           0x00004010,0x00404000,0x20404000,0x20000000,
786           0x20004000,0x00000010,0x20400010,0x00404000,
787           0x20404010,0x00400000,0x00004010,0x20000010,
788           0x00400000,0x20004000,0x20000000,0x00004010,
789           0x20000010,0x20404010,0x00404000,0x20400000,
790           0x00404010,0x20404000,0x00000000,0x20400010,
791           0x00000010,0x00004000,0x20400000,0x00404010,
792           0x00004000,0x00400010,0x20004010,0x00000000,
793           0x20404000,0x20000000,0x00400010,0x20004010 },
794         { 0x00200000,0x04200002,0x04000802,0x00000000,
795           0x00000800,0x04000802,0x00200802,0x04200800,
796           0x04200802,0x00200000,0x00000000,0x04000002,
797           0x00000002,0x04000000,0x04200002,0x00000802,
798           0x04000800,0x00200802,0x00200002,0x04000800,
799           0x04000002,0x04200000,0x04200800,0x00200002,
800           0x04200000,0x00000800,0x00000802,0x04200802,
801           0x00200800,0x00000002,0x04000000,0x00200800,
802           0x04000000,0x00200800,0x00200000,0x04000802,
803           0x04000802,0x04200002,0x04200002,0x00000002,
804           0x00200002,0x04000000,0x04000800,0x00200000,
805           0x04200800,0x00000802,0x00200802,0x04200800,
806           0x00000802,0x04000002,0x04200802,0x04200000,
807           0x00200800,0x00000000,0x00000002,0x04200802,
808           0x00000000,0x00200802,0x04200000,0x00000800,
809           0x04000002,0x04000800,0x00000800,0x00200002 },
810         { 0x10001040,0x00001000,0x00040000,0x10041040,
811           0x10000000,0x10001040,0x00000040,0x10000000,
812           0x00040040,0x10040000,0x10041040,0x00041000,
813           0x10041000,0x00041040,0x00001000,0x00000040,
814           0x10040000,0x10000040,0x10001000,0x00001040,
815           0x00041000,0x00040040,0x10040040,0x10041000,
816           0x00001040,0x00000000,0x00000000,0x10040040,
817           0x10000040,0x10001000,0x00041040,0x00040000,
818           0x00041040,0x00040000,0x10041000,0x00001000,
819           0x00000040,0x10040040,0x00001000,0x00041040,
820           0x10001000,0x00000040,0x10000040,0x10040000,
821           0x10040040,0x10000000,0x00040000,0x10001040,
822           0x00000000,0x10041040,0x00040040,0x10000040,
823           0x10040000,0x10001000,0x10001040,0x00000000,
824           0x10041040,0x00041000,0x00041000,0x00001040,
825           0x00001040,0x00040040,0x10000000,0x10041000 }
826 };
827
828 #undef F
829 #define F(l,r,key){\
830         work = ((r >> 4) | (r << 28)) ^ key[0];\
831         l ^= Spbox[6][work & 0x3f];\
832         l ^= Spbox[4][(work >> 8) & 0x3f];\
833         l ^= Spbox[2][(work >> 16) & 0x3f];\
834         l ^= Spbox[0][(work >> 24) & 0x3f];\
835         work = r ^ key[1];\
836         l ^= Spbox[7][work & 0x3f];\
837         l ^= Spbox[5][(work >> 8) & 0x3f];\
838         l ^= Spbox[3][(work >> 16) & 0x3f];\
839         l ^= Spbox[1][(work >> 24) & 0x3f];\
840 }
841 /* Encrypt or decrypt a block of data in ECB mode */
842 static void
843 des (guint32 ks[16][2], unsigned char block[8])
844 {
845         guint32 left,right,work;
846         
847         /* Read input block and place in left/right in big-endian order */
848         left = ((guint32)block[0] << 24)
849          | ((guint32)block[1] << 16)
850          | ((guint32)block[2] << 8)
851          | (guint32)block[3];
852         right = ((guint32)block[4] << 24)
853          | ((guint32)block[5] << 16)
854          | ((guint32)block[6] << 8)
855          | (guint32)block[7];
856
857         /* Hoey's clever initial permutation algorithm, from Outerbridge
858          * (see Schneier p 478) 
859          *
860          * The convention here is the same as Outerbridge: rotate each
861          * register left by 1 bit, i.e., so that "left" contains permuted
862          * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32    
863          * (using origin-1 numbering as in the FIPS). This allows us to avoid
864          * one of the two rotates that would otherwise be required in each of
865          * the 16 rounds.
866          */
867         work = ((left >> 4) ^ right) & 0x0f0f0f0f;
868         right ^= work;
869         left ^= work << 4;
870         work = ((left >> 16) ^ right) & 0xffff;
871         right ^= work;
872         left ^= work << 16;
873         work = ((right >> 2) ^ left) & 0x33333333;
874         left ^= work;
875         right ^= (work << 2);
876         work = ((right >> 8) ^ left) & 0xff00ff;
877         left ^= work;
878         right ^= (work << 8);
879         right = (right << 1) | (right >> 31);
880         work = (left ^ right) & 0xaaaaaaaa;
881         left ^= work;
882         right ^= work;
883         left = (left << 1) | (left >> 31);
884
885         /* Now do the 16 rounds */
886         F(left,right,ks[0]);
887         F(right,left,ks[1]);
888         F(left,right,ks[2]);
889         F(right,left,ks[3]);
890         F(left,right,ks[4]);
891         F(right,left,ks[5]);
892         F(left,right,ks[6]);
893         F(right,left,ks[7]);
894         F(left,right,ks[8]);
895         F(right,left,ks[9]);
896         F(left,right,ks[10]);
897         F(right,left,ks[11]);
898         F(left,right,ks[12]);
899         F(right,left,ks[13]);
900         F(left,right,ks[14]);
901         F(right,left,ks[15]);
902
903         /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
904         right = (right << 31) | (right >> 1);
905         work = (left ^ right) & 0xaaaaaaaa;
906         left ^= work;
907         right ^= work;
908         left = (left >> 1) | (left  << 31);
909         work = ((left >> 8) ^ right) & 0xff00ff;
910         right ^= work;
911         left ^= work << 8;
912         work = ((left >> 2) ^ right) & 0x33333333;
913         right ^= work;
914         left ^= work << 2;
915         work = ((right >> 16) ^ left) & 0xffff;
916         left ^= work;
917         right ^= work << 16;
918         work = ((right >> 4) ^ left) & 0x0f0f0f0f;
919         left ^= work;
920         right ^= work << 4;
921
922         /* Put the block back into the user's buffer with final swap */
923         block[0] = right >> 24;
924         block[1] = right >> 16;
925         block[2] = right >> 8;
926         block[3] = right;
927         block[4] = left >> 24;
928         block[5] = left >> 16;
929         block[6] = left >> 8;
930         block[7] = left;
931 }
932
933 /* Key schedule-related tables from FIPS-46 */
934
935 /* permuted choice table (key) */
936 static const unsigned char pc1[] = {
937         57, 49, 41, 33, 25, 17,  9,
938          1, 58, 50, 42, 34, 26, 18,
939         10,  2, 59, 51, 43, 35, 27,
940         19, 11,  3, 60, 52, 44, 36,
941
942         63, 55, 47, 39, 31, 23, 15,
943          7, 62, 54, 46, 38, 30, 22,
944         14,  6, 61, 53, 45, 37, 29,
945         21, 13,  5, 28, 20, 12,  4
946 };
947
948 /* number left rotations of pc1 */
949 static const unsigned char totrot[] = {
950         1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
951 };
952
953 /* permuted choice key (table) */
954 static const unsigned char pc2[] = {
955         14, 17, 11, 24,  1,  5,
956          3, 28, 15,  6, 21, 10,
957         23, 19, 12,  4, 26,  8,
958         16,  7, 27, 20, 13,  2,
959         41, 52, 31, 37, 47, 55,
960         30, 40, 51, 45, 33, 48,
961         44, 49, 39, 56, 34, 53,
962         46, 42, 50, 36, 29, 32
963 };
964
965 /* End of DES-defined tables */
966
967
968 /* bit 0 is left-most in byte */
969 static const int bytebit[] = {
970         0200,0100,040,020,010,04,02,01
971 };
972
973
974 /* Generate key schedule for encryption or decryption
975  * depending on the value of "decrypt"
976  */
977 static void
978 deskey (DES_KS k, unsigned char *key, int decrypt)
979 {
980         unsigned char pc1m[56];         /* place to modify pc1 into */
981         unsigned char pcr[56];          /* place to rotate pc1 into */
982         register int i,j,l;
983         int m;
984         unsigned char ks[8];
985
986         for (j=0; j<56; j++) {          /* convert pc1 to bits of key */
987                 l=pc1[j]-1;             /* integer bit location  */
988                 m = l & 07;             /* find bit              */
989                 pc1m[j]=(key[l>>3] &    /* find which key byte l is in */
990                         bytebit[m])     /* and which bit of that byte */
991                         ? 1 : 0;        /* and store 1-bit result */
992         }
993         for (i=0; i<16; i++) {          /* key chunk for each iteration */
994                 memset(ks,0,sizeof(ks));        /* Clear key schedule */
995                 for (j=0; j<56; j++)    /* rotate pc1 the right amount */
996                         pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28];
997                         /* rotate left and right halves independently */
998                 for (j=0; j<48; j++){   /* select bits individually */
999                         /* check bit that goes to ks[j] */
1000                         if (pcr[pc2[j]-1]){
1001                                 /* mask it in if it's there */
1002                                 l= j % 6;
1003                                 ks[j/6] |= bytebit[l] >> 2;
1004                         }
1005                 }
1006                 /* Now convert to packed odd/even interleaved form */
1007                 k[i][0] = ((guint32)ks[0] << 24)
1008                  | ((guint32)ks[2] << 16)
1009                  | ((guint32)ks[4] << 8)
1010                  | ((guint32)ks[6]);
1011                 k[i][1] = ((guint32)ks[1] << 24)
1012                  | ((guint32)ks[3] << 16)
1013                  | ((guint32)ks[5] << 8)
1014                  | ((guint32)ks[7]);
1015         }
1016 }