1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-auth-ntlm.c: HTTP NTLM Authentication helper
5 * Copyright (C) 2007 Red Hat, Inc.
17 #include "soup-auth-ntlm.h"
19 #include "soup-message-private.h"
21 static void soup_ntlm_lanmanager_hash (const char *password,
23 static void soup_ntlm_nt_hash (const char *password,
25 static char *soup_ntlm_request (void);
26 static gboolean soup_ntlm_parse_challenge (const char *challenge,
28 char **default_domain);
29 static char *soup_ntlm_response (const char *nonce,
39 SOUP_NTLM_SENT_REQUEST,
40 SOUP_NTLM_RECEIVED_CHALLENGE,
41 SOUP_NTLM_SENT_RESPONSE,
48 char *response_header;
49 } SoupNTLMConnectionState;
52 char *username, *domain;
53 guchar nt_hash[21], lm_hash[21];
54 gboolean authenticated;
57 /* Use Samba's 'winbind' daemon to support NTLM single-sign-on,
58 * by delegating the NTLM challenge/response protocal to a helper
60 * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
61 * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
62 * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
64 gboolean sso_available;
68 } SoupAuthNTLMPrivate;
69 #define SOUP_AUTH_NTLM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMPrivate))
72 static gboolean ntlm_auth_available, ntlm_auth_debug;
73 static void sso_ntlm_close (SoupAuthNTLMPrivate *priv);
77 * SOUP_TYPE_AUTH_NTLM:
79 * A #GType corresponding to HTTP-based NTLM authentication.
80 * #SoupSessions do not support this type by default; if you want to
81 * enable support for it, call soup_session_add_feature_by_type(),
82 * passing %SOUP_TYPE_AUTH_NTLM.
87 G_DEFINE_TYPE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_CONNECTION_AUTH)
90 soup_auth_ntlm_init (SoupAuthNTLM *ntlm)
93 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (ntlm);
94 const char *username = NULL, *slash;
96 priv->sso_available = TRUE;
100 username = getenv ("NTLMUSER");
102 username = g_get_user_name ();
104 slash = strpbrk (username, "\\/");
106 priv->username = g_strdup (slash + 1);
107 priv->domain = g_strndup (username, slash - username);
109 priv->username = g_strdup (username);
116 soup_auth_ntlm_finalize (GObject *object)
118 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (object);
120 g_free (priv->username);
121 g_free (priv->domain);
123 memset (priv->nt_hash, 0, sizeof (priv->nt_hash));
124 memset (priv->lm_hash, 0, sizeof (priv->lm_hash));
127 sso_ntlm_close (priv);
130 G_OBJECT_CLASS (soup_auth_ntlm_parent_class)->finalize (object);
135 sso_ntlm_close (SoupAuthNTLMPrivate *priv)
137 if (priv->fd_in != -1) {
142 if (priv->fd_out != -1) {
143 close (priv->fd_out);
149 sso_ntlm_initiate (SoupAuthNTLMPrivate *priv)
154 if (!priv->sso_available)
157 if (!ntlm_auth_available && !ntlm_auth_debug) {
158 priv->sso_available = FALSE;
162 /* Return if ntlm_auth execution process exist already */
163 if (priv->fd_in != -1 && priv->fd_out != -1)
166 /* Clean all sso data before re-initiate */
167 sso_ntlm_close (priv);
170 if (ntlm_auth_debug) {
171 argv[0] = (char *) g_getenv ("SOUP_NTLM_AUTH_DEBUG");
173 priv->sso_available = FALSE;
178 argv[1] = "--helper-protocol";
179 argv[2] = "ntlmssp-client-1";
180 argv[3] = "--use-cached-creds";
181 argv[4] = "--username";
182 argv[5] = priv->username;
183 argv[6] = priv->domain ? "--domain" : NULL;
184 argv[7] = priv->domain;
187 ret = g_spawn_async_with_pipes (NULL, argv, NULL,
188 G_SPAWN_STDERR_TO_DEV_NULL,
190 NULL, &priv->fd_in, &priv->fd_out,
193 priv->sso_available = FALSE;
198 sso_ntlm_response (SoupAuthNTLMPrivate *priv, const char *input, SoupNTLMState conn_state)
203 size_t len_in = strlen (input), len_out = sizeof (buf);
206 int written = write (priv->fd_in, input, len_in);
210 /* write failed if other errors happen */
217 while (len_out > 0) {
218 size = read (priv->fd_out, tmpbuf, len_out);
223 } else if (size == 0)
225 else if (tmpbuf[size - 1] == '\n') {
226 tmpbuf[size - 1] = '\0';
235 if (g_ascii_strcasecmp (buf, "PW") == 0) {
236 /* Samba/winbind installed but not configured */
237 return g_strdup ("PW");
239 if (conn_state == SOUP_NTLM_NEW &&
240 g_ascii_strncasecmp (buf, "YR ", 3) != 0) {
241 /* invalid response for type 1 message */
244 if (conn_state == SOUP_NTLM_RECEIVED_CHALLENGE &&
245 g_ascii_strncasecmp (buf, "KK ", 3) != 0 &&
246 g_ascii_strncasecmp (buf, "AF ", 3) != 0) {
247 /* invalid response for type 3 message */
251 return g_strdup_printf ("NTLM %.*s", (int)(size - 4), buf + 3);
253 #endif /* USE_NTLM_AUTH */
256 soup_auth_ntlm_create_connection_state (SoupConnectionAuth *auth)
258 SoupNTLMConnectionState *conn;
260 conn = g_slice_new0 (SoupNTLMConnectionState);
261 conn->state = SOUP_NTLM_NEW;
267 soup_auth_ntlm_free_connection_state (SoupConnectionAuth *auth,
270 SoupNTLMConnectionState *conn = state;
272 g_free (conn->nonce);
273 g_free (conn->response_header);
274 g_slice_free (SoupNTLMConnectionState, conn);
278 soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg,
279 const char *auth_header, gpointer state)
281 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth);
282 SoupNTLMConnectionState *conn = state;
283 gboolean success = TRUE;
285 if (conn->state > SOUP_NTLM_SENT_REQUEST) {
286 /* We already authenticated, but then got another 401.
287 * That means "permission denied", so don't try to
288 * authenticate again.
290 conn->state = SOUP_NTLM_FAILED;
292 /* FIXME: we should only do this if the password never worked */
293 priv->authenticated = FALSE;
298 if (!g_str_has_prefix (auth_header, "NTLM "))
301 if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce, &priv->domain)) {
302 conn->state = SOUP_NTLM_FAILED;
307 if (priv->sso_available && conn->state == SOUP_NTLM_SENT_REQUEST) {
308 char *input, *response;
310 /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */
311 if (!sso_ntlm_initiate (priv)) {
312 conn->state = SOUP_NTLM_SSO_FAILED;
317 input = g_strdup_printf ("TT %s\n", auth_header + 5);
318 response = sso_ntlm_response (priv, input, conn->state);
319 sso_ntlm_close (priv);
323 conn->state = SOUP_NTLM_SSO_FAILED;
325 } else if (!g_ascii_strcasecmp (response, "PW")) {
326 priv->sso_available = FALSE;
329 conn->response_header = response;
330 priv->authenticated = TRUE;
336 if (conn->state == SOUP_NTLM_SENT_REQUEST)
337 conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
339 g_object_set (G_OBJECT (auth),
340 SOUP_AUTH_REALM, priv->domain,
341 SOUP_AUTH_HOST, soup_message_get_uri (msg)->host,
347 soup_auth_ntlm_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
351 space = g_strdup (source_uri->path);
353 /* Strip query and filename component */
354 p = strrchr (space, '/');
355 if (p && p != space && p[1])
358 return g_slist_prepend (NULL, space);
362 soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username,
363 const char *password)
365 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth);
368 g_return_if_fail (username != NULL);
369 g_return_if_fail (password != NULL);
372 g_free (priv->username);
374 g_free (priv->domain);
376 slash = strpbrk (username, "\\/");
378 priv->domain = g_strndup (username, slash - username);
379 priv->username = g_strdup (slash + 1);
381 priv->domain = g_strdup ("");
382 priv->username = g_strdup (username);
385 soup_ntlm_nt_hash (password, priv->nt_hash);
386 soup_ntlm_lanmanager_hash (password, priv->lm_hash);
388 priv->authenticated = TRUE;
392 soup_auth_ntlm_is_authenticated (SoupAuth *auth)
394 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth);
396 return priv->authenticated;
400 soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth,
404 SoupNTLMConnectionState *conn = state;
406 return conn->state != SOUP_NTLM_FAILED && conn->state != SOUP_NTLM_SSO_FAILED;
410 soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth,
414 SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth);
415 SoupNTLMConnectionState *conn = state;
418 switch (conn->state) {
421 if (sso_ntlm_initiate (priv)) {
422 header = sso_ntlm_response (priv, "YR\n", conn->state);
424 if (g_ascii_strcasecmp (header, "PW") != 0) {
425 conn->state = SOUP_NTLM_SENT_REQUEST;
430 priv->sso_available = FALSE;
433 g_warning ("NTLM single-sign-on using %s failed", NTLM_AUTH);
436 /* If NTLM single-sign-on fails, go back to original
437 * request handling process.
440 header = soup_ntlm_request ();
441 conn->state = SOUP_NTLM_SENT_REQUEST;
443 case SOUP_NTLM_RECEIVED_CHALLENGE:
444 if (conn->response_header) {
445 header = conn->response_header;
446 conn->response_header = NULL;
448 header = soup_ntlm_response (conn->nonce,
455 g_clear_pointer (&conn->nonce, g_free);
456 conn->state = SOUP_NTLM_SENT_RESPONSE;
459 case SOUP_NTLM_SSO_FAILED:
460 /* Restart request without SSO */
461 g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH);
462 priv->sso_available = FALSE;
463 header = soup_ntlm_request ();
464 conn->state = SOUP_NTLM_SENT_REQUEST;
475 soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class)
477 SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_ntlm_class);
478 SoupConnectionAuthClass *connauth_class = SOUP_CONNECTION_AUTH_CLASS (auth_ntlm_class);
479 GObjectClass *object_class = G_OBJECT_CLASS (auth_ntlm_class);
481 g_type_class_add_private (auth_ntlm_class, sizeof (SoupAuthNTLMPrivate));
483 auth_class->scheme_name = "NTLM";
484 auth_class->strength = 3;
486 auth_class->get_protection_space = soup_auth_ntlm_get_protection_space;
487 auth_class->authenticate = soup_auth_ntlm_authenticate;
488 auth_class->is_authenticated = soup_auth_ntlm_is_authenticated;
490 connauth_class->create_connection_state = soup_auth_ntlm_create_connection_state;
491 connauth_class->free_connection_state = soup_auth_ntlm_free_connection_state;
492 connauth_class->update_connection = soup_auth_ntlm_update_connection;
493 connauth_class->get_connection_authorization = soup_auth_ntlm_get_connection_authorization;
494 connauth_class->is_connection_ready = soup_auth_ntlm_is_connection_ready;
496 object_class->finalize = soup_auth_ntlm_finalize;
499 ntlm_auth_available = g_file_test (NTLM_AUTH, G_FILE_TEST_IS_EXECUTABLE);
500 ntlm_auth_debug = (g_getenv ("SOUP_NTLM_AUTH_DEBUG") != NULL);
504 static void md4sum (const unsigned char *in,
506 unsigned char digest[16]);
508 typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */
510 static void deskey (DES_KS, unsigned char *, int);
512 static void des (DES_KS, unsigned char *);
514 static void setup_schedule (const guchar *key_56, DES_KS ks);
516 static void calc_response (const guchar *key,
517 const guchar *plaintext,
520 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
521 "\x4B\x47\x53\x21\x40\x23\x24\x25" \
522 "\x00\x00\x00\x00\x00"
525 soup_ntlm_lanmanager_hash (const char *password, guchar hash[21])
527 guchar lm_password [15];
531 for (i = 0; i < 14 && password [i]; i++)
532 lm_password [i] = g_ascii_toupper ((unsigned char) password [i]);
535 lm_password [i] = '\0';
537 memcpy (hash, LM_PASSWORD_MAGIC, 21);
539 setup_schedule (lm_password, ks);
542 setup_schedule (lm_password + 7, ks);
547 soup_ntlm_nt_hash (const char *password, guchar hash[21])
549 unsigned char *buf, *p;
551 p = buf = g_malloc (strlen (password) * 2);
558 md4sum (buf, p - buf, hash);
559 memset (hash + 16, 0, 5);
571 #define NTLM_CHALLENGE_NONCE_OFFSET 24
572 #define NTLM_CHALLENGE_NONCE_LENGTH 8
573 #define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
575 #define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
576 #define NTLM_RESPONSE_FLAGS 0x8201
586 NTLMString session_key;
592 ntlm_set_string (NTLMString *string, int *offset, int len)
594 string->offset = GUINT16_TO_LE (*offset);
595 string->length = string->length2 = GUINT16_TO_LE (len);
600 soup_ntlm_request (void)
602 return g_strdup ("NTLM TlRMTVNTUAABAAAABYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
606 soup_ntlm_parse_challenge (const char *challenge,
608 char **default_domain)
614 chall = g_base64_decode (challenge, &clen);
615 if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET ||
616 clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) {
621 if (default_domain) {
622 memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain));
623 domain.length = GUINT16_FROM_LE (domain.length);
624 domain.offset = GUINT16_FROM_LE (domain.offset);
626 if (clen < domain.length + domain.offset) {
631 *default_domain = g_convert ((char *)chall + domain.offset,
632 domain.length, "UTF-8", "UCS-2LE",
637 *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET,
638 NTLM_CHALLENGE_NONCE_LENGTH);
646 soup_ntlm_response (const char *nonce,
654 gsize hlen, dlen, ulen;
655 guchar lm_resp[24], nt_resp[24];
656 char *user_conv, *host_conv, *domain_conv;
661 calc_response (nt_hash, (guchar *)nonce, nt_resp);
662 calc_response (lm_hash, (guchar *)nonce, lm_resp);
664 memset (&resp, 0, sizeof (resp));
665 memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header));
666 resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS);
668 offset = sizeof (resp);
673 domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL);
674 user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL);
675 host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL);
677 ntlm_set_string (&resp.domain, &offset, dlen);
678 ntlm_set_string (&resp.user, &offset, ulen);
679 ntlm_set_string (&resp.host, &offset, hlen);
680 ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp));
681 ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp));
683 out = g_malloc (((offset + 3) * 4) / 3 + 6);
684 strncpy (out, "NTLM ", 5);
689 p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp),
690 FALSE, p, &state, &save);
691 p += g_base64_encode_step ((const guchar *) domain_conv, dlen,
692 FALSE, p, &state, &save);
693 p += g_base64_encode_step ((const guchar *) user_conv, ulen,
694 FALSE, p, &state, &save);
695 p += g_base64_encode_step ((const guchar *) host_conv, hlen,
696 FALSE, p, &state, &save);
697 p += g_base64_encode_step (lm_resp, sizeof (lm_resp),
698 FALSE, p, &state, &save);
699 p += g_base64_encode_step (nt_resp, sizeof (nt_resp),
700 FALSE, p, &state, &save);
701 p += g_base64_encode_close (FALSE, p, &state, &save);
704 g_free (domain_conv);
712 /* Set up a key schedule based on a 56bit key */
714 setup_schedule (const guchar *key_56, DES_KS ks)
719 key[0] = (key_56[0]) ;
720 key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF);
721 key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF);
722 key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF);
723 key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF);
724 key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF);
725 key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF);
726 key[7] = ((key_56[6] << 1) & 0xFF);
729 for (i = 0; i < 8; i++) {
730 for (c = bit = 0; bit < 8; bit++)
731 if (key[i] & (1 << bit))
741 calc_response (const guchar *key, const guchar *plaintext, guchar *results)
745 memcpy (results, plaintext, 8);
746 memcpy (results + 8, plaintext, 8);
747 memcpy (results + 16, plaintext, 8);
749 setup_schedule (key, ks);
752 setup_schedule (key + 7, ks);
753 des (ks, results + 8);
755 setup_schedule (key + 14, ks);
756 des (ks, results + 16);
761 * MD4 encoder. (The one everyone else uses is not GPL-compatible;
762 * this is a reimplementation from spec.) This doesn't need to be
763 * efficient for our purposes, although it would be nice to fix
764 * it to not malloc()...
767 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
768 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
769 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
770 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
773 md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
776 guint32 A, B, C, D, AA, BB, CC, DD, X[16];
777 int pbytes, nbits = nbytes * 8, i, j;
779 pbytes = (120 - (nbytes % 64)) % 64;
780 M = alloca (nbytes + pbytes + 8);
781 memcpy (M, in, nbytes);
782 memset (M + nbytes, 0, pbytes + 8);
784 M[nbytes + pbytes] = nbits & 0xFF;
785 M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF;
786 M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF;
787 M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF;
794 for (i = 0; i < nbytes + pbytes + 8; i += 64) {
795 for (j = 0; j < 16; j++) {
796 X[j] = (M[i + j*4]) |
797 (M[i + j*4 + 1] << 8) |
798 (M[i + j*4 + 2] << 16) |
799 (M[i + j*4 + 3] << 24);
807 A = ROT (A + F(B, C, D) + X[0], 3);
808 D = ROT (D + F(A, B, C) + X[1], 7);
809 C = ROT (C + F(D, A, B) + X[2], 11);
810 B = ROT (B + F(C, D, A) + X[3], 19);
811 A = ROT (A + F(B, C, D) + X[4], 3);
812 D = ROT (D + F(A, B, C) + X[5], 7);
813 C = ROT (C + F(D, A, B) + X[6], 11);
814 B = ROT (B + F(C, D, A) + X[7], 19);
815 A = ROT (A + F(B, C, D) + X[8], 3);
816 D = ROT (D + F(A, B, C) + X[9], 7);
817 C = ROT (C + F(D, A, B) + X[10], 11);
818 B = ROT (B + F(C, D, A) + X[11], 19);
819 A = ROT (A + F(B, C, D) + X[12], 3);
820 D = ROT (D + F(A, B, C) + X[13], 7);
821 C = ROT (C + F(D, A, B) + X[14], 11);
822 B = ROT (B + F(C, D, A) + X[15], 19);
824 A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3);
825 D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5);
826 C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9);
827 B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
828 A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3);
829 D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5);
830 C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9);
831 B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
832 A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3);
833 D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5);
834 C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
835 B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
836 A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3);
837 D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5);
838 C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
839 B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
841 A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3);
842 D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9);
843 C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11);
844 B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
845 A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3);
846 D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
847 C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11);
848 B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
849 A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3);
850 D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9);
851 C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11);
852 B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
853 A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3);
854 D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
855 C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11);
856 B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
864 digest[0] = A & 0xFF;
865 digest[1] = (A >> 8) & 0xFF;
866 digest[2] = (A >> 16) & 0xFF;
867 digest[3] = (A >> 24) & 0xFF;
868 digest[4] = B & 0xFF;
869 digest[5] = (B >> 8) & 0xFF;
870 digest[6] = (B >> 16) & 0xFF;
871 digest[7] = (B >> 24) & 0xFF;
872 digest[8] = C & 0xFF;
873 digest[9] = (C >> 8) & 0xFF;
874 digest[10] = (C >> 16) & 0xFF;
875 digest[11] = (C >> 24) & 0xFF;
876 digest[12] = D & 0xFF;
877 digest[13] = (D >> 8) & 0xFF;
878 digest[14] = (D >> 16) & 0xFF;
879 digest[15] = (D >> 24) & 0xFF;
883 /* Public domain DES implementation from Phil Karn */
884 static const guint32 Spbox[8][64] = {
885 { 0x01010400,0x00000000,0x00010000,0x01010404,
886 0x01010004,0x00010404,0x00000004,0x00010000,
887 0x00000400,0x01010400,0x01010404,0x00000400,
888 0x01000404,0x01010004,0x01000000,0x00000004,
889 0x00000404,0x01000400,0x01000400,0x00010400,
890 0x00010400,0x01010000,0x01010000,0x01000404,
891 0x00010004,0x01000004,0x01000004,0x00010004,
892 0x00000000,0x00000404,0x00010404,0x01000000,
893 0x00010000,0x01010404,0x00000004,0x01010000,
894 0x01010400,0x01000000,0x01000000,0x00000400,
895 0x01010004,0x00010000,0x00010400,0x01000004,
896 0x00000400,0x00000004,0x01000404,0x00010404,
897 0x01010404,0x00010004,0x01010000,0x01000404,
898 0x01000004,0x00000404,0x00010404,0x01010400,
899 0x00000404,0x01000400,0x01000400,0x00000000,
900 0x00010004,0x00010400,0x00000000,0x01010004 },
901 { 0x80108020,0x80008000,0x00008000,0x00108020,
902 0x00100000,0x00000020,0x80100020,0x80008020,
903 0x80000020,0x80108020,0x80108000,0x80000000,
904 0x80008000,0x00100000,0x00000020,0x80100020,
905 0x00108000,0x00100020,0x80008020,0x00000000,
906 0x80000000,0x00008000,0x00108020,0x80100000,
907 0x00100020,0x80000020,0x00000000,0x00108000,
908 0x00008020,0x80108000,0x80100000,0x00008020,
909 0x00000000,0x00108020,0x80100020,0x00100000,
910 0x80008020,0x80100000,0x80108000,0x00008000,
911 0x80100000,0x80008000,0x00000020,0x80108020,
912 0x00108020,0x00000020,0x00008000,0x80000000,
913 0x00008020,0x80108000,0x00100000,0x80000020,
914 0x00100020,0x80008020,0x80000020,0x00100020,
915 0x00108000,0x00000000,0x80008000,0x00008020,
916 0x80000000,0x80100020,0x80108020,0x00108000 },
917 { 0x00000208,0x08020200,0x00000000,0x08020008,
918 0x08000200,0x00000000,0x00020208,0x08000200,
919 0x00020008,0x08000008,0x08000008,0x00020000,
920 0x08020208,0x00020008,0x08020000,0x00000208,
921 0x08000000,0x00000008,0x08020200,0x00000200,
922 0x00020200,0x08020000,0x08020008,0x00020208,
923 0x08000208,0x00020200,0x00020000,0x08000208,
924 0x00000008,0x08020208,0x00000200,0x08000000,
925 0x08020200,0x08000000,0x00020008,0x00000208,
926 0x00020000,0x08020200,0x08000200,0x00000000,
927 0x00000200,0x00020008,0x08020208,0x08000200,
928 0x08000008,0x00000200,0x00000000,0x08020008,
929 0x08000208,0x00020000,0x08000000,0x08020208,
930 0x00000008,0x00020208,0x00020200,0x08000008,
931 0x08020000,0x08000208,0x00000208,0x08020000,
932 0x00020208,0x00000008,0x08020008,0x00020200 },
933 { 0x00802001,0x00002081,0x00002081,0x00000080,
934 0x00802080,0x00800081,0x00800001,0x00002001,
935 0x00000000,0x00802000,0x00802000,0x00802081,
936 0x00000081,0x00000000,0x00800080,0x00800001,
937 0x00000001,0x00002000,0x00800000,0x00802001,
938 0x00000080,0x00800000,0x00002001,0x00002080,
939 0x00800081,0x00000001,0x00002080,0x00800080,
940 0x00002000,0x00802080,0x00802081,0x00000081,
941 0x00800080,0x00800001,0x00802000,0x00802081,
942 0x00000081,0x00000000,0x00000000,0x00802000,
943 0x00002080,0x00800080,0x00800081,0x00000001,
944 0x00802001,0x00002081,0x00002081,0x00000080,
945 0x00802081,0x00000081,0x00000001,0x00002000,
946 0x00800001,0x00002001,0x00802080,0x00800081,
947 0x00002001,0x00002080,0x00800000,0x00802001,
948 0x00000080,0x00800000,0x00002000,0x00802080 },
949 { 0x00000100,0x02080100,0x02080000,0x42000100,
950 0x00080000,0x00000100,0x40000000,0x02080000,
951 0x40080100,0x00080000,0x02000100,0x40080100,
952 0x42000100,0x42080000,0x00080100,0x40000000,
953 0x02000000,0x40080000,0x40080000,0x00000000,
954 0x40000100,0x42080100,0x42080100,0x02000100,
955 0x42080000,0x40000100,0x00000000,0x42000000,
956 0x02080100,0x02000000,0x42000000,0x00080100,
957 0x00080000,0x42000100,0x00000100,0x02000000,
958 0x40000000,0x02080000,0x42000100,0x40080100,
959 0x02000100,0x40000000,0x42080000,0x02080100,
960 0x40080100,0x00000100,0x02000000,0x42080000,
961 0x42080100,0x00080100,0x42000000,0x42080100,
962 0x02080000,0x00000000,0x40080000,0x42000000,
963 0x00080100,0x02000100,0x40000100,0x00080000,
964 0x00000000,0x40080000,0x02080100,0x40000100 },
965 { 0x20000010,0x20400000,0x00004000,0x20404010,
966 0x20400000,0x00000010,0x20404010,0x00400000,
967 0x20004000,0x00404010,0x00400000,0x20000010,
968 0x00400010,0x20004000,0x20000000,0x00004010,
969 0x00000000,0x00400010,0x20004010,0x00004000,
970 0x00404000,0x20004010,0x00000010,0x20400010,
971 0x20400010,0x00000000,0x00404010,0x20404000,
972 0x00004010,0x00404000,0x20404000,0x20000000,
973 0x20004000,0x00000010,0x20400010,0x00404000,
974 0x20404010,0x00400000,0x00004010,0x20000010,
975 0x00400000,0x20004000,0x20000000,0x00004010,
976 0x20000010,0x20404010,0x00404000,0x20400000,
977 0x00404010,0x20404000,0x00000000,0x20400010,
978 0x00000010,0x00004000,0x20400000,0x00404010,
979 0x00004000,0x00400010,0x20004010,0x00000000,
980 0x20404000,0x20000000,0x00400010,0x20004010 },
981 { 0x00200000,0x04200002,0x04000802,0x00000000,
982 0x00000800,0x04000802,0x00200802,0x04200800,
983 0x04200802,0x00200000,0x00000000,0x04000002,
984 0x00000002,0x04000000,0x04200002,0x00000802,
985 0x04000800,0x00200802,0x00200002,0x04000800,
986 0x04000002,0x04200000,0x04200800,0x00200002,
987 0x04200000,0x00000800,0x00000802,0x04200802,
988 0x00200800,0x00000002,0x04000000,0x00200800,
989 0x04000000,0x00200800,0x00200000,0x04000802,
990 0x04000802,0x04200002,0x04200002,0x00000002,
991 0x00200002,0x04000000,0x04000800,0x00200000,
992 0x04200800,0x00000802,0x00200802,0x04200800,
993 0x00000802,0x04000002,0x04200802,0x04200000,
994 0x00200800,0x00000000,0x00000002,0x04200802,
995 0x00000000,0x00200802,0x04200000,0x00000800,
996 0x04000002,0x04000800,0x00000800,0x00200002 },
997 { 0x10001040,0x00001000,0x00040000,0x10041040,
998 0x10000000,0x10001040,0x00000040,0x10000000,
999 0x00040040,0x10040000,0x10041040,0x00041000,
1000 0x10041000,0x00041040,0x00001000,0x00000040,
1001 0x10040000,0x10000040,0x10001000,0x00001040,
1002 0x00041000,0x00040040,0x10040040,0x10041000,
1003 0x00001040,0x00000000,0x00000000,0x10040040,
1004 0x10000040,0x10001000,0x00041040,0x00040000,
1005 0x00041040,0x00040000,0x10041000,0x00001000,
1006 0x00000040,0x10040040,0x00001000,0x00041040,
1007 0x10001000,0x00000040,0x10000040,0x10040000,
1008 0x10040040,0x10000000,0x00040000,0x10001040,
1009 0x00000000,0x10041040,0x00040040,0x10000040,
1010 0x10040000,0x10001000,0x10001040,0x00000000,
1011 0x10041040,0x00041000,0x00041000,0x00001040,
1012 0x00001040,0x00040040,0x10000000,0x10041000 }
1016 #define F(l,r,key){\
1017 work = ((r >> 4) | (r << 28)) ^ key[0];\
1018 l ^= Spbox[6][work & 0x3f];\
1019 l ^= Spbox[4][(work >> 8) & 0x3f];\
1020 l ^= Spbox[2][(work >> 16) & 0x3f];\
1021 l ^= Spbox[0][(work >> 24) & 0x3f];\
1023 l ^= Spbox[7][work & 0x3f];\
1024 l ^= Spbox[5][(work >> 8) & 0x3f];\
1025 l ^= Spbox[3][(work >> 16) & 0x3f];\
1026 l ^= Spbox[1][(work >> 24) & 0x3f];\
1028 /* Encrypt or decrypt a block of data in ECB mode */
1030 des (guint32 ks[16][2], unsigned char block[8])
1032 guint32 left,right,work;
1034 /* Read input block and place in left/right in big-endian order */
1035 left = ((guint32)block[0] << 24)
1036 | ((guint32)block[1] << 16)
1037 | ((guint32)block[2] << 8)
1038 | (guint32)block[3];
1039 right = ((guint32)block[4] << 24)
1040 | ((guint32)block[5] << 16)
1041 | ((guint32)block[6] << 8)
1042 | (guint32)block[7];
1044 /* Hoey's clever initial permutation algorithm, from Outerbridge
1045 * (see Schneier p 478)
1047 * The convention here is the same as Outerbridge: rotate each
1048 * register left by 1 bit, i.e., so that "left" contains permuted
1049 * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
1050 * (using origin-1 numbering as in the FIPS). This allows us to avoid
1051 * one of the two rotates that would otherwise be required in each of
1054 work = ((left >> 4) ^ right) & 0x0f0f0f0f;
1057 work = ((left >> 16) ^ right) & 0xffff;
1060 work = ((right >> 2) ^ left) & 0x33333333;
1062 right ^= (work << 2);
1063 work = ((right >> 8) ^ left) & 0xff00ff;
1065 right ^= (work << 8);
1066 right = (right << 1) | (right >> 31);
1067 work = (left ^ right) & 0xaaaaaaaa;
1070 left = (left << 1) | (left >> 31);
1072 /* Now do the 16 rounds */
1073 F(left,right,ks[0]);
1074 F(right,left,ks[1]);
1075 F(left,right,ks[2]);
1076 F(right,left,ks[3]);
1077 F(left,right,ks[4]);
1078 F(right,left,ks[5]);
1079 F(left,right,ks[6]);
1080 F(right,left,ks[7]);
1081 F(left,right,ks[8]);
1082 F(right,left,ks[9]);
1083 F(left,right,ks[10]);
1084 F(right,left,ks[11]);
1085 F(left,right,ks[12]);
1086 F(right,left,ks[13]);
1087 F(left,right,ks[14]);
1088 F(right,left,ks[15]);
1090 /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
1091 right = (right << 31) | (right >> 1);
1092 work = (left ^ right) & 0xaaaaaaaa;
1095 left = (left >> 1) | (left << 31);
1096 work = ((left >> 8) ^ right) & 0xff00ff;
1099 work = ((left >> 2) ^ right) & 0x33333333;
1102 work = ((right >> 16) ^ left) & 0xffff;
1104 right ^= work << 16;
1105 work = ((right >> 4) ^ left) & 0x0f0f0f0f;
1109 /* Put the block back into the user's buffer with final swap */
1110 block[0] = right >> 24;
1111 block[1] = right >> 16;
1112 block[2] = right >> 8;
1114 block[4] = left >> 24;
1115 block[5] = left >> 16;
1116 block[6] = left >> 8;
1120 /* Key schedule-related tables from FIPS-46 */
1122 /* permuted choice table (key) */
1123 static const unsigned char pc1[] = {
1124 57, 49, 41, 33, 25, 17, 9,
1125 1, 58, 50, 42, 34, 26, 18,
1126 10, 2, 59, 51, 43, 35, 27,
1127 19, 11, 3, 60, 52, 44, 36,
1129 63, 55, 47, 39, 31, 23, 15,
1130 7, 62, 54, 46, 38, 30, 22,
1131 14, 6, 61, 53, 45, 37, 29,
1132 21, 13, 5, 28, 20, 12, 4
1135 /* number left rotations of pc1 */
1136 static const unsigned char totrot[] = {
1137 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
1140 /* permuted choice key (table) */
1141 static const unsigned char pc2[] = {
1142 14, 17, 11, 24, 1, 5,
1143 3, 28, 15, 6, 21, 10,
1144 23, 19, 12, 4, 26, 8,
1145 16, 7, 27, 20, 13, 2,
1146 41, 52, 31, 37, 47, 55,
1147 30, 40, 51, 45, 33, 48,
1148 44, 49, 39, 56, 34, 53,
1149 46, 42, 50, 36, 29, 32
1152 /* End of DES-defined tables */
1155 /* bit 0 is left-most in byte */
1156 static const int bytebit[] = {
1157 0200,0100,040,020,010,04,02,01
1161 /* Generate key schedule for encryption or decryption
1162 * depending on the value of "decrypt"
1165 deskey (DES_KS k, unsigned char *key, int decrypt)
1167 unsigned char pc1m[56]; /* place to modify pc1 into */
1168 unsigned char pcr[56]; /* place to rotate pc1 into */
1171 unsigned char ks[8];
1173 for (j=0; j<56; j++) { /* convert pc1 to bits of key */
1174 l=pc1[j]-1; /* integer bit location */
1175 m = l & 07; /* find bit */
1176 pc1m[j]=(key[l>>3] & /* find which key byte l is in */
1177 bytebit[m]) /* and which bit of that byte */
1178 ? 1 : 0; /* and store 1-bit result */
1180 for (i=0; i<16; i++) { /* key chunk for each iteration */
1181 memset(ks,0,sizeof(ks)); /* Clear key schedule */
1182 for (j=0; j<56; j++) /* rotate pc1 the right amount */
1183 pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28];
1184 /* rotate left and right halves independently */
1185 for (j=0; j<48; j++){ /* select bits individually */
1186 /* check bit that goes to ks[j] */
1188 /* mask it in if it's there */
1190 ks[j/6] |= bytebit[l] >> 2;
1193 /* Now convert to packed odd/even interleaved form */
1194 k[i][0] = ((guint32)ks[0] << 24)
1195 | ((guint32)ks[2] << 16)
1196 | ((guint32)ks[4] << 8)
1198 k[i][1] = ((guint32)ks[1] << 24)
1199 | ((guint32)ks[3] << 16)
1200 | ((guint32)ks[5] << 8)