aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-08-21 00:04:12 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2010-08-21 00:04:12 +0100
commita366cca62d3a55db4f12a94584f7e7f8fa00db02 (patch)
treeb870cec2e826793beb9257e43e77b7b409a33add
parent801b90b3e76f6eed7027f46a7d11e3d3fe0e04e9 (diff)
Now including a nice and compact 3DES implementation done by Christophe
Devine. OpenSSL exports nice cipher functions, but GnuTLS only just started doing this in 2.10 or so (not even in Debian Sid yet). So instead of adding a whole library for encrypting 72 bytes of data, let's have a built-in 3DES implementation for a while..
-rwxr-xr-xconfigure6
-rw-r--r--lib/Makefile2
-rw-r--r--lib/des.c646
-rw-r--r--lib/des.h51
4 files changed, 704 insertions, 1 deletions
diff --git a/configure b/configure
index 9b77604c..b0035438 100755
--- a/configure
+++ b/configure
@@ -422,6 +422,12 @@ if [ "$ret" = "0" ]; then
exit 1
fi;
+if [ "$msn" = "1" -a "$ssl" != "openssl" ]; then
+ # Needed for MSN only. OpenSSL exports nice cipher functions already,
+ # others don't, so use our own 3des code.
+ echo 'DES=des.o' >> Makefile.settings
+fi
+
echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings
if detect_resolv_dynamic || detect_resolv_static; then
diff --git a/lib/Makefile b/lib/Makefile
index bebe3ba6..7e19fb76 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -12,7 +12,7 @@ SRCDIR := $(SRCDIR)lib/
endif
# [SH] Program variables
-objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
+objects = arc.o base64.o $(DES) $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
LFLAGS += -r
diff --git a/lib/des.c b/lib/des.c
new file mode 100644
index 00000000..3b9cc8d5
--- /dev/null
+++ b/lib/des.c
@@ -0,0 +1,646 @@
+/*
+ * FIPS-46-3 compliant 3DES implementation
+ *
+ * Copyright (C) 2001-2003 Christophe Devine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Modified for BitlBee: Added a function compatible with the existing
+ * function in ssl_openssl.c, fairly specialised for MSN auth (since that's
+ * all this is used for at least for now).
+ *
+ * Added some consts to the tables at the top, and disabled some 64-bit
+ * and 128-bit key code that I don't need.
+ *
+ * *Many* thanks to Christophe for this compact and easy to import code.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "des.h"
+
+/* the eight DES S-boxes */
+
+static const uint32_t SB1[64] =
+{
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/* PC1: left and right halves bit-swap */
+
+static const uint32_t LHs[16] =
+{
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+ 0x00000000, 0x01000000, 0x00010000, 0x01010000,
+ 0x00000100, 0x01000100, 0x00010100, 0x01010100,
+ 0x00000001, 0x01000001, 0x00010001, 0x01010001,
+ 0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/* platform-independant 32-bit integer manipulation macros */
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (uint8_t) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (uint8_t) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (uint8_t) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (uint8_t) ( (n) ); \
+}
+
+/* Initial Permutation macro */
+
+#define DES_IP(X,Y) \
+{ \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
+ X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
+}
+
+/* Final Permutation macro */
+
+#define DES_FP(X,Y) \
+{ \
+ X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
+ Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+}
+
+/* DES round macro */
+
+#define DES_ROUND(X,Y) \
+{ \
+ T = *SK++ ^ X; \
+ Y ^= SB8[ (T ) & 0x3F ] ^ \
+ SB6[ (T >> 8) & 0x3F ] ^ \
+ SB4[ (T >> 16) & 0x3F ] ^ \
+ SB2[ (T >> 24) & 0x3F ]; \
+ \
+ T = *SK++ ^ ((X << 28) | (X >> 4)); \
+ Y ^= SB7[ (T ) & 0x3F ] ^ \
+ SB5[ (T >> 8) & 0x3F ] ^ \
+ SB3[ (T >> 16) & 0x3F ] ^ \
+ SB1[ (T >> 24) & 0x3F ]; \
+}
+
+/* DES key schedule */
+
+int des_main_ks( uint32_t SK[32], const uint8_t key[8] )
+{
+ int i;
+ uint32_t X, Y, T;
+
+ GET_UINT32( X, key, 0 );
+ GET_UINT32( Y, key, 4 );
+
+ /* Permuted Choice 1 */
+
+ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
+ T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
+
+ X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
+ | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
+ | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+ | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+ Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
+ | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
+ | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+ | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+ X &= 0x0FFFFFFF;
+ Y &= 0x0FFFFFFF;
+
+ /* calculate subkeys */
+
+ for( i = 0; i < 16; i++ )
+ {
+ if( i < 2 || i == 8 || i == 15 )
+ {
+ X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
+ Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
+ }
+ else
+ {
+ X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
+ Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
+ }
+
+ *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
+ | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+ | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
+ | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
+ | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
+ | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
+ | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
+ | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
+ | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+ | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+ | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+ *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+ | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+ | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
+ | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+ | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
+ | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
+ | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
+ | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
+ | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
+ | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
+ | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+ }
+
+ return( 0 );
+}
+
+#if TEST
+int des_set_key( des_context *ctx, uint8_t key[8] )
+{
+ int i;
+
+ /* setup encryption subkeys */
+
+ des_main_ks( ctx->esk, key );
+
+ /* setup decryption subkeys */
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ ctx->dsk[i ] = ctx->esk[30 - i];
+ ctx->dsk[i + 1] = ctx->esk[31 - i];
+ }
+
+ return( 0 );
+}
+
+/* DES 64-bit block encryption/decryption */
+
+void des_crypt( uint32_t SK[32], uint8_t input[8], uint8_t output[8] )
+{
+ uint32_t X, Y, T;
+
+ GET_UINT32( X, input, 0 );
+ GET_UINT32( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+
+ DES_FP( Y, X );
+
+ PUT_UINT32( Y, output, 0 );
+ PUT_UINT32( X, output, 4 );
+}
+
+void des_encrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] )
+{
+ des_crypt( ctx->esk, input, output );
+}
+
+void des_decrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] )
+{
+ des_crypt( ctx->dsk, input, output );
+}
+
+/* Triple-DES key schedule */
+
+int des3_set_2keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8] )
+{
+ int i;
+
+ des_main_ks( ctx->esk , key1 );
+ des_main_ks( ctx->dsk + 32, key2 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ ctx->dsk[i ] = ctx->esk[30 - i];
+ ctx->dsk[i + 1] = ctx->esk[31 - i];
+
+ ctx->esk[i + 32] = ctx->dsk[62 - i];
+ ctx->esk[i + 33] = ctx->dsk[63 - i];
+
+ ctx->esk[i + 64] = ctx->esk[ i];
+ ctx->esk[i + 65] = ctx->esk[ 1 + i];
+
+ ctx->dsk[i + 64] = ctx->dsk[ i];
+ ctx->dsk[i + 65] = ctx->dsk[ 1 + i];
+ }
+
+ return( 0 );
+}
+#endif
+
+int des3_set_3keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8],
+ const uint8_t key3[8] )
+{
+ int i;
+
+ des_main_ks( ctx->esk , key1 );
+ des_main_ks( ctx->dsk + 32, key2 );
+ des_main_ks( ctx->esk + 64, key3 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ ctx->dsk[i ] = ctx->esk[94 - i];
+ ctx->dsk[i + 1] = ctx->esk[95 - i];
+
+ ctx->esk[i + 32] = ctx->dsk[62 - i];
+ ctx->esk[i + 33] = ctx->dsk[63 - i];
+
+ ctx->dsk[i + 64] = ctx->esk[30 - i];
+ ctx->dsk[i + 65] = ctx->esk[31 - i];
+ }
+
+ return( 0 );
+}
+
+/* Triple-DES 64-bit block encryption/decryption */
+
+void des3_crypt( uint32_t SK[96], uint8_t input[8], uint8_t output[8] )
+{
+ uint32_t X, Y, T;
+
+ GET_UINT32( X, input, 0 );
+ GET_UINT32( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+ DES_ROUND( X, Y ); DES_ROUND( Y, X );
+
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+ DES_ROUND( Y, X ); DES_ROUND( X, Y );
+
+ DES_FP( Y, X );
+
+ PUT_UINT32( Y, output, 0 );
+ PUT_UINT32( X, output, 4 );
+}
+
+void des3_encrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] )
+{
+ des3_crypt( ctx->esk, input, output );
+}
+
+void des3_decrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] )
+{
+ des3_crypt( ctx->dsk, input, output );
+}
+
+size_t ssl_des3_encrypt( const unsigned char *key, size_t key_len, const unsigned char *input,
+ size_t input_len, const unsigned char *iv, unsigned char **res )
+{
+ des3_context ctx3;
+ size_t off;
+ uint8_t buf[8];
+
+ /* Keep it simple, for as long as this is just used for MSN auth anyway. */
+ if( key_len != 24 || ( input_len % 8 ) != 0 )
+ return 0;
+
+ *res = g_malloc( input_len );
+ des3_set_3keys( &ctx3, key, key + 8, key + 16 );
+
+ /* This loop does CBC 3DES. */
+ memcpy( buf, iv, 8 );
+ for( off = 0; off < input_len; off += 8 )
+ {
+ int i;
+
+ for( i = 0; i < 8; i ++ )
+ buf[i] ^= input[off+i];
+ des3_encrypt( &ctx3, buf, buf );
+ memcpy( *res + off, buf, 8 );
+ }
+
+ return input_len;
+}
+
+#ifdef TEST
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Triple-DES Monte Carlo Test: ECB mode
+ * source: NIST - tripledes-vectors.zip
+ */
+
+static const unsigned char DES3_keys[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01 },
+ { 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 }
+};
+
+static const unsigned char DES3_init[8] =
+{
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char DES3_enc_test[3][8] =
+{
+ { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+ { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+ { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+static const unsigned char DES3_dec_test[3][8] =
+{
+ { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+ { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+ { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+int main( void )
+{
+ int m, n, i;
+ des_context ctx;
+ des3_context ctx3;
+ unsigned char buf[8];
+
+ for( m = 0; m < 2; m++ )
+ {
+ printf( "\n Triple-DES Monte Carlo Test (ECB mode) - " );
+
+ if( m == 0 ) printf( "encryption\n\n" );
+ if( m == 1 ) printf( "decryption\n\n" );
+
+ for( n = 0; n < 3; n++ )
+ {
+ printf( " Test %d, key size = %3d bits: ",
+ n + 1, 64 + n * 64 );
+
+ fflush( stdout );
+
+ memcpy( buf, DES3_init, 8 );
+
+ switch( n )
+ {
+ case 0:
+ des_set_key( &ctx, DES3_keys[0] );
+ break;
+
+ case 1:
+ des3_set_2keys( &ctx3, DES3_keys[0],
+ DES3_keys[1] );
+ break;
+
+ case 2:
+ des3_set_3keys( &ctx3, DES3_keys[0],
+ DES3_keys[1],
+ DES3_keys[2] );
+ break;
+ }
+
+ for( i = 0; i < 10000; i++ )
+ {
+ if( n == 0 )
+ {
+ if( m == 0 ) des_encrypt( &ctx, buf, buf );
+ if( m == 1 ) des_decrypt( &ctx, buf, buf );
+ }
+ else
+ {
+ if( m == 0 ) des3_encrypt( &ctx3, buf, buf );
+ if( m == 1 ) des3_decrypt( &ctx3, buf, buf );
+ }
+ }
+
+ if( ( m == 0 && memcmp( buf, DES3_enc_test[n], 8 ) ) ||
+ ( m == 1 && memcmp( buf, DES3_dec_test[n], 8 ) ) )
+ {
+ printf( "failed!\n" );
+ return( 1 );
+ }
+
+ printf( "passed.\n" );
+ }
+ }
+
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
diff --git a/lib/des.h b/lib/des.h
new file mode 100644
index 00000000..92fbfd22
--- /dev/null
+++ b/lib/des.h
@@ -0,0 +1,51 @@
+/*
+ * FIPS-46-3 compliant 3DES implementation
+ *
+ * Copyright (C) 2001-2003 Christophe Devine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _DES_H
+#define _DES_H
+
+#include <stdint.h>
+
+typedef struct
+{
+ uint32_t esk[32]; /* DES encryption subkeys */
+ uint32_t dsk[32]; /* DES decryption subkeys */
+}
+des_context;
+
+typedef struct
+{
+ uint32_t esk[96]; /* Triple-DES encryption subkeys */
+ uint32_t dsk[96]; /* Triple-DES decryption subkeys */
+}
+des3_context;
+
+int des_set_key( des_context *ctx, uint8_t key[8] );
+void des_encrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] );
+void des_decrypt( des_context *ctx, uint8_t input[8], uint8_t output[8] );
+
+int des3_set_2keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8] );
+int des3_set_3keys( des3_context *ctx, const uint8_t key1[8], const uint8_t key2[8],
+ const uint8_t key3[8] );
+
+void des3_encrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] );
+void des3_decrypt( des3_context *ctx, uint8_t input[8], uint8_t output[8] );
+
+#endif /* des.h */