New DES implementation, replacing Eric Young's. All of PuTTY is now
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 10 Mar 2000 17:27:20 +0000 (17:27 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 10 Mar 2000 17:27:20 +0000 (17:27 +0000)
under my own copyright and there are no tricky licensing issues!

git-svn-id: svn://svn.tartarus.org/sgt/putty@398 cda61777-01e9-0310-a592-d414129be87e

LICENCE
sshdes.c
win_res.rc

diff --git a/LICENCE b/LICENCE
index c3bfcce..4632573 100644 (file)
--- a/LICENCE
+++ b/LICENCE
@@ -1,5 +1,4 @@
-PuTTY is copyright 1997-1999 Simon Tatham. Portions copyright Eric
-Young.
+PuTTY is copyright 1997-2000 Simon Tatham.
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation files
index 83d4d26..eace658 100644 (file)
--- a/sshdes.c
+++ b/sshdes.c
 #include <assert.h>
 #include "ssh.h"
 
+/* des.c - implementation of DES
+ */
+
 /*
+ * Description of DES
+ *
+ * Unlike the description in FIPS 46, I'm going to use _sensible_ indices:
+ * bits in an n-bit word are numbered from 0 at the LSB to n-1 at the MSB.
+ * And S-boxes are indexed by six consecutive bits, not by the outer two
+ * followed by the middle four.
+ *
+ * The DES encryption routine requires a 64-bit input, and a key schedule K
+ * containing 16 48-bit elements.
+ *
+ *   First the input is permuted by the initial permutation IP.
+ *   Then the input is split into 32-bit words L and R. (L is the MSW.)
+ *   Next, 16 rounds. In each round:
+ *     (L, R) <- (R, L xor f(R, K[i]))
+ *   Then the pre-output words L and R are swapped.
+ *   Then L and R are glued back together into a 64-bit word. (L is the MSW,
+ *     again, but since we just swapped them, the MSW is the R that came out
+ *     of the last round.)
+ *   The 64-bit output block is permuted by the inverse of IP and returned.
+ *
+ * Decryption is identical except that the elements of K are used in the
+ * opposite order. (This wouldn't work if that word swap didn't happen.)
+ *
+ * The function f, used in each round, accepts a 32-bit word R and a
+ * 48-bit key block K. It produces a 32-bit output.
+ *
+ *   First R is expanded to 48 bits using the bit-selection function E.
+ *   The resulting 48-bit block is XORed with the key block K to produce
+ *     a 48-bit block X.
+ *   This block X is split into eight groups of 6 bits. Each group of 6
+ *     bits is then looked up in one of the eight S-boxes to convert
+ *     it to 4 bits. These eight groups of 4 bits are glued back
+ *     together to produce a 32-bit preoutput block.
+ *   The preoutput block is permuted using the permutation P and returned.
+ *
+ * Key setup maps a 64-bit key word into a 16x48-bit key schedule. Although
+ * the approved input format for the key is a 64-bit word, eight of the
+ * bits are discarded, so the actual quantity of key used is 56 bits.
+ *
+ *   First the input key is converted to two 28-bit words C and D using
+ *     the bit-selection function PC1.
+ *   Then 16 rounds of key setup occur. In each round, C and D are each
+ *     rotated left by either 1 or 2 bits (depending on which round), and
+ *     then converted into a key schedule element using the bit-selection
+ *     function PC2.
+ *
+ * That's the actual algorithm. Now for the tedious details: all those
+ * painful permutations and lookup tables.
+ *
+ * IP is a 64-to-64 bit permutation. Its output contains the following
+ * bits of its input (listed in order MSB to LSB of output).
+ *
+ *    6 14 22 30 38 46 54 62  4 12 20 28 36 44 52 60
+ *    2 10 18 26 34 42 50 58  0  8 16 24 32 40 48 56
+ *    7 15 23 31 39 47 55 63  5 13 21 29 37 45 53 61
+ *    3 11 19 27 35 43 51 59  1  9 17 25 33 41 49 57
+ *
+ * E is a 32-to-48 bit selection function. Its output contains the following
+ * bits of its input (listed in order MSB to LSB of output).
+ *
+ *    0 31 30 29 28 27 28 27 26 25 24 23 24 23 22 21 20 19 20 19 18 17 16 15
+ *   16 15 14 13 12 11 12 11 10  9  8  7  8  7  6  5  4  3  4  3  2  1  0 31
+ *
+ * The S-boxes are arbitrary table-lookups each mapping a 6-bit input to a
+ * 4-bit output. In other words, each S-box is an array[64] of 4-bit numbers.
+ * The S-boxes are listed below. The first S-box listed is applied to the
+ * most significant six bits of the block X; the last one is applied to the
+ * least significant.
+ *
+ *   14  0  4 15 13  7  1  4  2 14 15  2 11 13  8  1
+ *    3 10 10  6  6 12 12 11  5  9  9  5  0  3  7  8
+ *    4 15  1 12 14  8  8  2 13  4  6  9  2  1 11  7
+ *   15  5 12 11  9  3  7 14  3 10 10  0  5  6  0 13
+ *
+ *   15  3  1 13  8  4 14  7  6 15 11  2  3  8  4 14
+ *    9 12  7  0  2  1 13 10 12  6  0  9  5 11 10  5
+ *    0 13 14  8  7 10 11  1 10  3  4 15 13  4  1  2
+ *    5 11  8  6 12  7  6 12  9  0  3  5  2 14 15  9
+ *
+ *   10 13  0  7  9  0 14  9  6  3  3  4 15  6  5 10
+ *    1  2 13  8 12  5  7 14 11 12  4 11  2 15  8  1
+ *   13  1  6 10  4 13  9  0  8  6 15  9  3  8  0  7
+ *   11  4  1 15  2 14 12  3  5 11 10  5 14  2  7 12
+ *
+ *    7 13 13  8 14 11  3  5  0  6  6 15  9  0 10  3
+ *    1  4  2  7  8  2  5 12 11  1 12 10  4 14 15  9
+ *   10  3  6 15  9  0  0  6 12 10 11  1  7 13 13  8
+ *   15  9  1  4  3  5 14 11  5 12  2  7  8  2  4 14
+ *
+ *    2 14 12 11  4  2  1 12  7  4 10  7 11 13  6  1
+ *    8  5  5  0  3 15 15 10 13  3  0  9 14  8  9  6
+ *    4 11  2  8  1 12 11  7 10  1 13 14  7  2  8 13
+ *   15  6  9 15 12  0  5  9  6 10  3  4  0  5 14  3
+ *
+ *   12 10  1 15 10  4 15  2  9  7  2 12  6  9  8  5
+ *    0  6 13  1  3 13  4 14 14  0  7 11  5  3 11  8
+ *    9  4 14  3 15  2  5 12  2  9  8  5 12 15  3 10
+ *    7 11  0 14  4  1 10  7  1  6 13  0 11  8  6 13
+ *
+ *    4 13 11  0  2 11 14  7 15  4  0  9  8  1 13 10
+ *    3 14 12  3  9  5  7 12  5  2 10 15  6  8  1  6
+ *    1  6  4 11 11 13 13  8 12  1  3  4  7 10 14  7
+ *   10  9 15  5  6  0  8 15  0 14  5  2  9  3  2 12
+ *
+ *   13  1  2 15  8 13  4  8  6 10 15  3 11  7  1  4
+ *   10 12  9  5  3  6 14 11  5  0  0 14 12  9  7  2
+ *    7  2 11  1  4 14  1  7  9  4 12 10 14  8  2 13
+ *    0 15  6 12 10  9 13  0 15  3  3  5  5  6  8 11
+ *
+ * P is a 32-to-32 bit permutation. Its output contains the following
+ * bits of its input (listed in order MSB to LSB of output).
+ *
+ *   16 25 12 11  3 20  4 15 31 17  9  6 27 14  1 22
+ *   30 24  8 18  0  5 29 23 13 19  2 26 10 21 28  7
+ *
+ * PC1 is a 64-to-56 bit selection function. Its output is in two words,
+ * C and D. The word C contains the following bits of its input (listed
+ * in order MSB to LSB of output).
+ *
+ *    7 15 23 31 39 47 55 63  6 14 22 30 38 46
+ *   54 62  5 13 21 29 37 45 53 61  4 12 20 28
+ *
+ * And the word D contains these bits.
+ *
+ *    1  9 17 25 33 41 49 57  2 10 18 26 34 42
+ *   50 58  3 11 19 27 35 43 51 59 36 44 52 60
+ *
+ * PC2 is a 56-to-48 bit selection function. Its input is in two words,
+ * C and D. These are treated as one 56-bit word (with C more significant,
+ * so that bits 55 to 28 of the word are bits 27 to 0 of C, and bits 27 to
+ * 0 of the word are bits 27 to 0 of D). The output contains the following
+ * bits of this 56-bit input word (listed in order MSB to LSB of output).
+ *
+ *   42 39 45 32 55 51 53 28 41 50 35 46 33 37 44 52 30 48 40 49 29 36 43 54
+ *   15  4 25 19  9  1 26 16  5 11 23  8 12  7 17  0 22  3 10 14  6 20 27 24
+ */
+
+typedef struct {
+    word32 k0246[16], k1357[16];
+    word32 eiv0, eiv1;
+    word32 div0, div1;
+} DESContext;
 
-DES implementation; 1995 Tatu Ylonen <ylo@cs.hut.fi>
+#define rotl(x, c) ( (x << c) | (x >> (32-c)) )
+#define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF)
 
-This implementation is derived from libdes-3.06, which is copyright
-(c) 1993 Eric Young, and distributed under the GNU GPL or the ARTISTIC licence
-(at the user's option).  The original distribution can be found e.g. from
-ftp://ftp.dsi.unimi.it/pub/security/crypt/libdes/libdes-3.06.tar.gz.
+static word32 bitsel(word32 *input, const int *bitnums, int size) {
+    word32 ret = 0;
+    while (size--) {
+        int bitpos = *bitnums++;
+        ret <<= 1;
+        if (bitpos >= 0)
+            ret |= 1 & (input[bitpos / 32] >> (bitpos % 32));
+    }
+    return ret;
+}
 
-This implementation is distributed under the same terms.  See
-libdes-README, libdes-ARTISTIC, and libdes-COPYING for more
-information.
+void des_key_setup(word32 key_msw, word32 key_lsw, DESContext *sched) {
+
+    static const int PC1_Cbits[] = {
+        7, 15, 23, 31, 39, 47, 55, 63, 6, 14, 22, 30, 38, 46,
+        54, 62, 5, 13, 21, 29, 37, 45, 53, 61, 4, 12, 20, 28
+    };
+    static const int PC1_Dbits[] = {
+        1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42,
+        50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 36, 44, 52, 60
+    };
+    static const int PC2_0246[] = {
+        49, 36, 59, 55, -1, -1, 37, 41, 48, 56, 34, 52, -1, -1, 15, 4,
+        25, 19, 9, 1, -1, -1, 12, 7, 17, 0, 22, 3, -1, -1, 46, 43
+    };
+    static const int PC2_1357[] = {
+        -1, -1, 57, 32, 45, 54, 39, 50, -1, -1, 44, 53, 33, 40, 47, 58,
+        -1, -1, 26, 16, 5, 11, 23, 8, -1, -1, 10, 14, 6, 20, 27, 24
+    };
+    static const int leftshifts[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
+
+    word32 C, D;
+    word32 buf[2];
+    int i;
+
+    buf[0] = key_lsw;
+    buf[1] = key_msw;
+
+    C = bitsel(buf, PC1_Cbits, 28);
+    D = bitsel(buf, PC1_Dbits, 28);
+
+    for (i = 0; i < 16; i++) {
+        C = rotl28(C, leftshifts[i]);
+        D = rotl28(D, leftshifts[i]);
+        buf[0] = D;
+        buf[1] = C;
+        sched->k0246[i] = bitsel(buf, PC2_0246, 32);
+        sched->k1357[i] = bitsel(buf, PC2_1357, 32);
+    }
 
-*/
+    sched->eiv0 = sched->eiv1 = 0;
+    sched->div0 = sched->div1 = 0;       /* for good measure */
+}
 
-typedef struct
-{
-  word32 key_schedule[32];
-} DESContext;
+static const word32 SPboxes[8][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, 0x01010004L},
+
+    {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, 0x00108000L},
+
+    {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, 0x00020200L},
+
+    {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, 0x00802080L},
+
+    {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, 0x40000100L},
+
+    {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, 0x20004010L},
+
+    {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, 0x00200002L},
+
+    {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, 0x10041000L}
+};
 
-/* Sets the des key for the context.  Initializes the context.  The least
-   significant bit of each byte of the key is ignored as parity. */
-static void des_set_key(unsigned char *key, DESContext *ks);
-
-/* Encrypts 32 bits in l,r, and stores the result in output[0] and output[1].
-   Performs encryption if encrypt is non-zero, and decryption if it is zero.
-   The key context must have been initialized previously with des_set_key. */
-static void des_encrypt(word32 l, word32 r, word32 *output, DESContext *ks,
-                       int encrypt);
-
-/* Encrypts len bytes from src to dest in CBC modes.  Len must be a multiple
-   of 8.  iv will be modified at end to a value suitable for continuing
-   encryption. */
-static void des_cbc_encrypt(DESContext *ks, unsigned char *iv, unsigned char *dest,
-                    const unsigned char *src, unsigned int len);
-
-/* Decrypts len bytes from src to dest in CBC modes.  Len must be a multiple
-   of 8.  iv will be modified at end to a value suitable for continuing
-   decryption. */
-static void des_cbc_decrypt(DESContext *ks, unsigned char *iv, unsigned char *dest,
-                    const unsigned char *src, unsigned int len);
-
-/* Encrypts in CBC mode using triple-DES. */
-static void des_3cbc_encrypt(DESContext *ks1, unsigned char *iv1, 
-                     DESContext *ks2, unsigned char *iv2,
-                     DESContext *ks3, unsigned char *iv3,
-                     unsigned char *dest, const unsigned char *src,
-                     unsigned int len);
-
-/* Decrypts in CBC mode using triple-DES. */
-static void des_3cbc_decrypt(DESContext *ks1, unsigned char *iv1,
-                     DESContext *ks2, unsigned char *iv2,
-                     DESContext *ks3, unsigned char *iv3,
-                     unsigned char *dest, const unsigned char *src,
-                     unsigned int len);
-
-#define GET_32BIT_LSB_FIRST(cp) \
-  (((unsigned long)(unsigned char)(cp)[0]) | \
-  ((unsigned long)(unsigned char)(cp)[1] << 8) | \
-  ((unsigned long)(unsigned char)(cp)[2] << 16) | \
-  ((unsigned long)(unsigned char)(cp)[3] << 24))
-
-#define PUT_32BIT_LSB_FIRST(cp, value) do { \
-  (cp)[0] = (value); \
-  (cp)[1] = (value) >> 8; \
-  (cp)[2] = (value) >> 16; \
-  (cp)[3] = (value) >> 24; } while (0)
+#define f(R, K0246, K1357) (\
+    s0246 = R ^ K0246, \
+    s1357 = R ^ K1357, \
+    s0246 = rotl(s0246, 28), \
+    SPboxes[0] [(s0246 >> 24) & 0x3F] | \
+    SPboxes[1] [(s1357 >> 24) & 0x3F] | \
+    SPboxes[2] [(s0246 >> 16) & 0x3F] | \
+    SPboxes[3] [(s1357 >> 16) & 0x3F] | \
+    SPboxes[4] [(s0246 >>  8) & 0x3F] | \
+    SPboxes[5] [(s1357 >>  8) & 0x3F] | \
+    SPboxes[6] [(s0246      ) & 0x3F] | \
+    SPboxes[7] [(s1357      ) & 0x3F])
+
+#define bitswap(L, R, n, mask) (\
+    swap = mask & ( (R >> n) ^ L ), \
+    R ^= swap << n, \
+    L ^= swap)
+
+/* Initial permutation */
+#define IP(L, R) (\
+    bitswap(R, L,  4, 0x0F0F0F0F), \
+    bitswap(R, L, 16, 0x0000FFFF), \
+    bitswap(L, R,  2, 0x33333333), \
+    bitswap(L, R,  8, 0x00FF00FF), \
+    bitswap(R, L,  1, 0x55555555))
+
+/* Final permutation */
+#define FP(L, R) (\
+    bitswap(R, L,  1, 0x55555555), \
+    bitswap(L, R,  8, 0x00FF00FF), \
+    bitswap(L, R,  2, 0x33333333), \
+    bitswap(R, L, 16, 0x0000FFFF), \
+    bitswap(R, L,  4, 0x0F0F0F0F))
+
+void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) {
+    word32 swap, s0246, s1357;
+
+    IP(L, R);
+
+    L = rotl(L, 1);
+    R = rotl(R, 1);
+
+    L ^= f(R, sched->k0246[ 0], sched->k1357[ 0]);
+    R ^= f(L, sched->k0246[ 1], sched->k1357[ 1]);
+    L ^= f(R, sched->k0246[ 2], sched->k1357[ 2]);
+    R ^= f(L, sched->k0246[ 3], sched->k1357[ 3]);
+    L ^= f(R, sched->k0246[ 4], sched->k1357[ 4]);
+    R ^= f(L, sched->k0246[ 5], sched->k1357[ 5]);
+    L ^= f(R, sched->k0246[ 6], sched->k1357[ 6]);
+    R ^= f(L, sched->k0246[ 7], sched->k1357[ 7]);
+    L ^= f(R, sched->k0246[ 8], sched->k1357[ 8]);
+    R ^= f(L, sched->k0246[ 9], sched->k1357[ 9]);
+    L ^= f(R, sched->k0246[10], sched->k1357[10]);
+    R ^= f(L, sched->k0246[11], sched->k1357[11]);
+    L ^= f(R, sched->k0246[12], sched->k1357[12]);
+    R ^= f(L, sched->k0246[13], sched->k1357[13]);
+    L ^= f(R, sched->k0246[14], sched->k1357[14]);
+    R ^= f(L, sched->k0246[15], sched->k1357[15]);
+
+    L = rotl(L, 31);
+    R = rotl(R, 31);
+
+    swap = L; L = R; R = swap;
+
+    FP(L, R);
+
+    output[0] = L;
+    output[1] = R;
+}
 
-/*
+void des_decipher(word32 *output, word32 L, word32 R, DESContext *sched) {
+    word32 swap, s0246, s1357;
 
-DES implementation; 1995 Tatu Ylonen <ylo@cs.hut.fi>
-
-This implementation is derived from libdes-3.06, which is copyright
-(c) 1993 Eric Young, and distributed under the GNU GPL or the ARTISTIC licence
-(at the user's option).  The original distribution can be found e.g. from
-ftp://ftp.dsi.unimi.it/pub/security/crypt/libdes/libdes-3.06.tar.gz.
-
-This implementation is distributed under the same terms.  See
-libdes-README, libdes-ARTISTIC, and libdes-COPYING for more
-information.
-
-A description of the DES algorithm can be found in every modern book on
-cryptography and data security, including the following:
-
-  Bruce Schneier: Applied Cryptography.  John Wiley & Sons, 1994.
-
-  Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to 
-    Computer Security.  Prentice-Hall, 1989.
-
-  Man Young Rhee: Cryptography and Secure Data Communications.  McGraw-Hill, 
-    1994.
-
-*/
-
-/* Table for key generation.  This used to be in sk.h. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-static const word32 des_skb[8][64]={
-/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
-{ 0x00000000,0x00000010,0x20000000,0x20000010,
-0x00010000,0x00010010,0x20010000,0x20010010,
-0x00000800,0x00000810,0x20000800,0x20000810,
-0x00010800,0x00010810,0x20010800,0x20010810,
-0x00000020,0x00000030,0x20000020,0x20000030,
-0x00010020,0x00010030,0x20010020,0x20010030,
-0x00000820,0x00000830,0x20000820,0x20000830,
-0x00010820,0x00010830,0x20010820,0x20010830,
-0x00080000,0x00080010,0x20080000,0x20080010,
-0x00090000,0x00090010,0x20090000,0x20090010,
-0x00080800,0x00080810,0x20080800,0x20080810,
-0x00090800,0x00090810,0x20090800,0x20090810,
-0x00080020,0x00080030,0x20080020,0x20080030,
-0x00090020,0x00090030,0x20090020,0x20090030,
-0x00080820,0x00080830,0x20080820,0x20080830,
-0x00090820,0x00090830,0x20090820,0x20090830 },
-/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
-{ 0x00000000,0x02000000,0x00002000,0x02002000,
-0x00200000,0x02200000,0x00202000,0x02202000,
-0x00000004,0x02000004,0x00002004,0x02002004,
-0x00200004,0x02200004,0x00202004,0x02202004,
-0x00000400,0x02000400,0x00002400,0x02002400,
-0x00200400,0x02200400,0x00202400,0x02202400,
-0x00000404,0x02000404,0x00002404,0x02002404,
-0x00200404,0x02200404,0x00202404,0x02202404,
-0x10000000,0x12000000,0x10002000,0x12002000,
-0x10200000,0x12200000,0x10202000,0x12202000,
-0x10000004,0x12000004,0x10002004,0x12002004,
-0x10200004,0x12200004,0x10202004,0x12202004,
-0x10000400,0x12000400,0x10002400,0x12002400,
-0x10200400,0x12200400,0x10202400,0x12202400,
-0x10000404,0x12000404,0x10002404,0x12002404,
-0x10200404,0x12200404,0x10202404,0x12202404 },
-/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
-{ 0x00000000,0x00000001,0x00040000,0x00040001,
-0x01000000,0x01000001,0x01040000,0x01040001,
-0x00000002,0x00000003,0x00040002,0x00040003,
-0x01000002,0x01000003,0x01040002,0x01040003,
-0x00000200,0x00000201,0x00040200,0x00040201,
-0x01000200,0x01000201,0x01040200,0x01040201,
-0x00000202,0x00000203,0x00040202,0x00040203,
-0x01000202,0x01000203,0x01040202,0x01040203,
-0x08000000,0x08000001,0x08040000,0x08040001,
-0x09000000,0x09000001,0x09040000,0x09040001,
-0x08000002,0x08000003,0x08040002,0x08040003,
-0x09000002,0x09000003,0x09040002,0x09040003,
-0x08000200,0x08000201,0x08040200,0x08040201,
-0x09000200,0x09000201,0x09040200,0x09040201,
-0x08000202,0x08000203,0x08040202,0x08040203,
-0x09000202,0x09000203,0x09040202,0x09040203 },
-/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
-{ 0x00000000,0x00100000,0x00000100,0x00100100,
-0x00000008,0x00100008,0x00000108,0x00100108,
-0x00001000,0x00101000,0x00001100,0x00101100,
-0x00001008,0x00101008,0x00001108,0x00101108,
-0x04000000,0x04100000,0x04000100,0x04100100,
-0x04000008,0x04100008,0x04000108,0x04100108,
-0x04001000,0x04101000,0x04001100,0x04101100,
-0x04001008,0x04101008,0x04001108,0x04101108,
-0x00020000,0x00120000,0x00020100,0x00120100,
-0x00020008,0x00120008,0x00020108,0x00120108,
-0x00021000,0x00121000,0x00021100,0x00121100,
-0x00021008,0x00121008,0x00021108,0x00121108,
-0x04020000,0x04120000,0x04020100,0x04120100,
-0x04020008,0x04120008,0x04020108,0x04120108,
-0x04021000,0x04121000,0x04021100,0x04121100,
-0x04021008,0x04121008,0x04021108,0x04121108 },
-/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
-{ 0x00000000,0x10000000,0x00010000,0x10010000,
-0x00000004,0x10000004,0x00010004,0x10010004,
-0x20000000,0x30000000,0x20010000,0x30010000,
-0x20000004,0x30000004,0x20010004,0x30010004,
-0x00100000,0x10100000,0x00110000,0x10110000,
-0x00100004,0x10100004,0x00110004,0x10110004,
-0x20100000,0x30100000,0x20110000,0x30110000,
-0x20100004,0x30100004,0x20110004,0x30110004,
-0x00001000,0x10001000,0x00011000,0x10011000,
-0x00001004,0x10001004,0x00011004,0x10011004,
-0x20001000,0x30001000,0x20011000,0x30011000,
-0x20001004,0x30001004,0x20011004,0x30011004,
-0x00101000,0x10101000,0x00111000,0x10111000,
-0x00101004,0x10101004,0x00111004,0x10111004,
-0x20101000,0x30101000,0x20111000,0x30111000,
-0x20101004,0x30101004,0x20111004,0x30111004 },
-/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
-{ 0x00000000,0x08000000,0x00000008,0x08000008,
-0x00000400,0x08000400,0x00000408,0x08000408,
-0x00020000,0x08020000,0x00020008,0x08020008,
-0x00020400,0x08020400,0x00020408,0x08020408,
-0x00000001,0x08000001,0x00000009,0x08000009,
-0x00000401,0x08000401,0x00000409,0x08000409,
-0x00020001,0x08020001,0x00020009,0x08020009,
-0x00020401,0x08020401,0x00020409,0x08020409,
-0x02000000,0x0A000000,0x02000008,0x0A000008,
-0x02000400,0x0A000400,0x02000408,0x0A000408,
-0x02020000,0x0A020000,0x02020008,0x0A020008,
-0x02020400,0x0A020400,0x02020408,0x0A020408,
-0x02000001,0x0A000001,0x02000009,0x0A000009,
-0x02000401,0x0A000401,0x02000409,0x0A000409,
-0x02020001,0x0A020001,0x02020009,0x0A020009,
-0x02020401,0x0A020401,0x02020409,0x0A020409 },
-/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
-{ 0x00000000,0x00000100,0x00080000,0x00080100,
-0x01000000,0x01000100,0x01080000,0x01080100,
-0x00000010,0x00000110,0x00080010,0x00080110,
-0x01000010,0x01000110,0x01080010,0x01080110,
-0x00200000,0x00200100,0x00280000,0x00280100,
-0x01200000,0x01200100,0x01280000,0x01280100,
-0x00200010,0x00200110,0x00280010,0x00280110,
-0x01200010,0x01200110,0x01280010,0x01280110,
-0x00000200,0x00000300,0x00080200,0x00080300,
-0x01000200,0x01000300,0x01080200,0x01080300,
-0x00000210,0x00000310,0x00080210,0x00080310,
-0x01000210,0x01000310,0x01080210,0x01080310,
-0x00200200,0x00200300,0x00280200,0x00280300,
-0x01200200,0x01200300,0x01280200,0x01280300,
-0x00200210,0x00200310,0x00280210,0x00280310,
-0x01200210,0x01200310,0x01280210,0x01280310 },
-/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
-{ 0x00000000,0x04000000,0x00040000,0x04040000,
-0x00000002,0x04000002,0x00040002,0x04040002,
-0x00002000,0x04002000,0x00042000,0x04042000,
-0x00002002,0x04002002,0x00042002,0x04042002,
-0x00000020,0x04000020,0x00040020,0x04040020,
-0x00000022,0x04000022,0x00040022,0x04040022,
-0x00002020,0x04002020,0x00042020,0x04042020,
-0x00002022,0x04002022,0x00042022,0x04042022,
-0x00000800,0x04000800,0x00040800,0x04040800,
-0x00000802,0x04000802,0x00040802,0x04040802,
-0x00002800,0x04002800,0x00042800,0x04042800,
-0x00002802,0x04002802,0x00042802,0x04042802,
-0x00000820,0x04000820,0x00040820,0x04040820,
-0x00000822,0x04000822,0x00040822,0x04040822,
-0x00002820,0x04002820,0x00042820,0x04042820,
-0x00002822,0x04002822,0x00042822,0x04042822 }
-};
+    IP(L, R);
 
-/* Tables used for executing des.  This used to be in spr.h. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-static const word32 des_SPtrans[8][64]={
-/* nibble 0 */
-{ 0x00820200, 0x00020000, 0x80800000, 0x80820200,
-0x00800000, 0x80020200, 0x80020000, 0x80800000,
-0x80020200, 0x00820200, 0x00820000, 0x80000200,
-0x80800200, 0x00800000, 0x00000000, 0x80020000,
-0x00020000, 0x80000000, 0x00800200, 0x00020200,
-0x80820200, 0x00820000, 0x80000200, 0x00800200,
-0x80000000, 0x00000200, 0x00020200, 0x80820000,
-0x00000200, 0x80800200, 0x80820000, 0x00000000,
-0x00000000, 0x80820200, 0x00800200, 0x80020000,
-0x00820200, 0x00020000, 0x80000200, 0x00800200,
-0x80820000, 0x00000200, 0x00020200, 0x80800000,
-0x80020200, 0x80000000, 0x80800000, 0x00820000,
-0x80820200, 0x00020200, 0x00820000, 0x80800200,
-0x00800000, 0x80000200, 0x80020000, 0x00000000,
-0x00020000, 0x00800000, 0x80800200, 0x00820200,
-0x80000000, 0x80820000, 0x00000200, 0x80020200 },
-
-/* nibble 1 */
-{ 0x10042004, 0x00000000, 0x00042000, 0x10040000,
-0x10000004, 0x00002004, 0x10002000, 0x00042000,
-0x00002000, 0x10040004, 0x00000004, 0x10002000,
-0x00040004, 0x10042000, 0x10040000, 0x00000004,
-0x00040000, 0x10002004, 0x10040004, 0x00002000,
-0x00042004, 0x10000000, 0x00000000, 0x00040004,
-0x10002004, 0x00042004, 0x10042000, 0x10000004,
-0x10000000, 0x00040000, 0x00002004, 0x10042004,
-0x00040004, 0x10042000, 0x10002000, 0x00042004,
-0x10042004, 0x00040004, 0x10000004, 0x00000000,
-0x10000000, 0x00002004, 0x00040000, 0x10040004,
-0x00002000, 0x10000000, 0x00042004, 0x10002004,
-0x10042000, 0x00002000, 0x00000000, 0x10000004,
-0x00000004, 0x10042004, 0x00042000, 0x10040000,
-0x10040004, 0x00040000, 0x00002004, 0x10002000,
-0x10002004, 0x00000004, 0x10040000, 0x00042000 },
-
-/* nibble 2 */
-{ 0x41000000, 0x01010040, 0x00000040, 0x41000040,
-0x40010000, 0x01000000, 0x41000040, 0x00010040,
-0x01000040, 0x00010000, 0x01010000, 0x40000000,
-0x41010040, 0x40000040, 0x40000000, 0x41010000,
-0x00000000, 0x40010000, 0x01010040, 0x00000040,
-0x40000040, 0x41010040, 0x00010000, 0x41000000,
-0x41010000, 0x01000040, 0x40010040, 0x01010000,
-0x00010040, 0x00000000, 0x01000000, 0x40010040,
-0x01010040, 0x00000040, 0x40000000, 0x00010000,
-0x40000040, 0x40010000, 0x01010000, 0x41000040,
-0x00000000, 0x01010040, 0x00010040, 0x41010000,
-0x40010000, 0x01000000, 0x41010040, 0x40000000,
-0x40010040, 0x41000000, 0x01000000, 0x41010040,
-0x00010000, 0x01000040, 0x41000040, 0x00010040,
-0x01000040, 0x00000000, 0x41010000, 0x40000040,
-0x41000000, 0x40010040, 0x00000040, 0x01010000 },
-
-/* nibble 3 */
-{ 0x00100402, 0x04000400, 0x00000002, 0x04100402,
-0x00000000, 0x04100000, 0x04000402, 0x00100002,
-0x04100400, 0x04000002, 0x04000000, 0x00000402,
-0x04000002, 0x00100402, 0x00100000, 0x04000000,
-0x04100002, 0x00100400, 0x00000400, 0x00000002,
-0x00100400, 0x04000402, 0x04100000, 0x00000400,
-0x00000402, 0x00000000, 0x00100002, 0x04100400,
-0x04000400, 0x04100002, 0x04100402, 0x00100000,
-0x04100002, 0x00000402, 0x00100000, 0x04000002,
-0x00100400, 0x04000400, 0x00000002, 0x04100000,
-0x04000402, 0x00000000, 0x00000400, 0x00100002,
-0x00000000, 0x04100002, 0x04100400, 0x00000400,
-0x04000000, 0x04100402, 0x00100402, 0x00100000,
-0x04100402, 0x00000002, 0x04000400, 0x00100402,
-0x00100002, 0x00100400, 0x04100000, 0x04000402,
-0x00000402, 0x04000000, 0x04000002, 0x04100400 },
-
-/* nibble 4 */
-{ 0x02000000, 0x00004000, 0x00000100, 0x02004108,
-0x02004008, 0x02000100, 0x00004108, 0x02004000,
-0x00004000, 0x00000008, 0x02000008, 0x00004100,
-0x02000108, 0x02004008, 0x02004100, 0x00000000,
-0x00004100, 0x02000000, 0x00004008, 0x00000108,
-0x02000100, 0x00004108, 0x00000000, 0x02000008,
-0x00000008, 0x02000108, 0x02004108, 0x00004008,
-0x02004000, 0x00000100, 0x00000108, 0x02004100,
-0x02004100, 0x02000108, 0x00004008, 0x02004000,
-0x00004000, 0x00000008, 0x02000008, 0x02000100,
-0x02000000, 0x00004100, 0x02004108, 0x00000000,
-0x00004108, 0x02000000, 0x00000100, 0x00004008,
-0x02000108, 0x00000100, 0x00000000, 0x02004108,
-0x02004008, 0x02004100, 0x00000108, 0x00004000,
-0x00004100, 0x02004008, 0x02000100, 0x00000108,
-0x00000008, 0x00004108, 0x02004000, 0x02000008 },
-
-/* nibble 5 */
-{ 0x20000010, 0x00080010, 0x00000000, 0x20080800,
-0x00080010, 0x00000800, 0x20000810, 0x00080000,
-0x00000810, 0x20080810, 0x00080800, 0x20000000,
-0x20000800, 0x20000010, 0x20080000, 0x00080810,
-0x00080000, 0x20000810, 0x20080010, 0x00000000,
-0x00000800, 0x00000010, 0x20080800, 0x20080010,
-0x20080810, 0x20080000, 0x20000000, 0x00000810,
-0x00000010, 0x00080800, 0x00080810, 0x20000800,
-0x00000810, 0x20000000, 0x20000800, 0x00080810,
-0x20080800, 0x00080010, 0x00000000, 0x20000800,
-0x20000000, 0x00000800, 0x20080010, 0x00080000,
-0x00080010, 0x20080810, 0x00080800, 0x00000010,
-0x20080810, 0x00080800, 0x00080000, 0x20000810,
-0x20000010, 0x20080000, 0x00080810, 0x00000000,
-0x00000800, 0x20000010, 0x20000810, 0x20080800,
-0x20080000, 0x00000810, 0x00000010, 0x20080010 },
-
-/* nibble 6 */
-{ 0x00001000, 0x00000080, 0x00400080, 0x00400001,
-0x00401081, 0x00001001, 0x00001080, 0x00000000,
-0x00400000, 0x00400081, 0x00000081, 0x00401000,
-0x00000001, 0x00401080, 0x00401000, 0x00000081,
-0x00400081, 0x00001000, 0x00001001, 0x00401081,
-0x00000000, 0x00400080, 0x00400001, 0x00001080,
-0x00401001, 0x00001081, 0x00401080, 0x00000001,
-0x00001081, 0x00401001, 0x00000080, 0x00400000,
-0x00001081, 0x00401000, 0x00401001, 0x00000081,
-0x00001000, 0x00000080, 0x00400000, 0x00401001,
-0x00400081, 0x00001081, 0x00001080, 0x00000000,
-0x00000080, 0x00400001, 0x00000001, 0x00400080,
-0x00000000, 0x00400081, 0x00400080, 0x00001080,
-0x00000081, 0x00001000, 0x00401081, 0x00400000,
-0x00401080, 0x00000001, 0x00001001, 0x00401081,
-0x00400001, 0x00401080, 0x00401000, 0x00001001 },
-
-/* nibble 7 */
-{ 0x08200020, 0x08208000, 0x00008020, 0x00000000,
-0x08008000, 0x00200020, 0x08200000, 0x08208020,
-0x00000020, 0x08000000, 0x00208000, 0x00008020,
-0x00208020, 0x08008020, 0x08000020, 0x08200000,
-0x00008000, 0x00208020, 0x00200020, 0x08008000,
-0x08208020, 0x08000020, 0x00000000, 0x00208000,
-0x08000000, 0x00200000, 0x08008020, 0x08200020,
-0x00200000, 0x00008000, 0x08208000, 0x00000020,
-0x00200000, 0x00008000, 0x08000020, 0x08208020,
-0x00008020, 0x08000000, 0x00000000, 0x00208000,
-0x08200020, 0x08008020, 0x08008000, 0x00200020,
-0x08208000, 0x00000020, 0x00200020, 0x08008000,
-0x08208020, 0x00200000, 0x08200000, 0x08000020,
-0x00208000, 0x00008020, 0x08008020, 0x08200000,
-0x00000020, 0x08208000, 0x00208020, 0x00000000,
-0x08000000, 0x08200020, 0x00008000, 0x00208020 }};
-
-/* Some stuff that used to be in des_locl.h.  Heavily modified. */
-       /* IP and FP
-        * The problem is more of a geometric problem that random bit fiddling.
-        0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
-        8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
-       16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
-       24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
-
-       32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
-       40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
-       48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
-       56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
-
-       The output has been subject to swaps of the form
-       0 1 -> 3 1 but the odd and even bits have been put into
-       2 3    2 0
-       different words.  The main trick is to remember that
-       t=((l>>size)^r)&(mask);
-       r^=t;
-       l^=(t<<size);
-       can be used to swap and move bits between words.
-
-       So l =  0  1  2  3  r = 16 17 18 19
-               4  5  6  7      20 21 22 23
-               8  9 10 11      24 25 26 27
-              12 13 14 15      28 29 30 31
-       becomes (for size == 2 and mask == 0x3333)
-          t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19
-                6^20  7^21 -- --        4  5 20 21       6  7 22 23
-               10^24 11^25 -- --        8  9 24 25      10 11 24 25
-               14^28 15^29 -- --       12 13 28 29      14 15 28 29
-
-       Thanks for hints from Richard Outerbridge - he told me IP&FP
-       could be done in 15 xor, 10 shifts and 5 ands.
-       When I finally started to think of the problem in 2D
-       I first got ~42 operations without xors.  When I remembered
-       how to use xors :-) I got it to its final state.
-       */
-#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
-       (b)^=(t),\
-       (a)^=((t)<<(n)))
-
-#define IP(l,r,t) \
-       PERM_OP(r,l,t, 4,0x0f0f0f0f); \
-       PERM_OP(l,r,t,16,0x0000ffff); \
-       PERM_OP(r,l,t, 2,0x33333333); \
-       PERM_OP(l,r,t, 8,0x00ff00ff); \
-       PERM_OP(r,l,t, 1,0x55555555);
-
-#define FP(l,r,t) \
-       PERM_OP(l,r,t, 1,0x55555555); \
-       PERM_OP(r,l,t, 8,0x00ff00ff); \
-       PERM_OP(l,r,t, 2,0x33333333); \
-       PERM_OP(r,l,t,16,0x0000ffff); \
-       PERM_OP(l,r,t, 4,0x0f0f0f0f);
-
-#define D_ENCRYPT(L,R,S)       \
-       u=(R^s[S  ]); \
-       t=R^s[S+1]; \
-       t=((t>>4)+(t<<28)); \
-       L^=     des_SPtrans[1][(t    )&0x3f]| \
-               des_SPtrans[3][(t>> 8)&0x3f]| \
-               des_SPtrans[5][(t>>16)&0x3f]| \
-               des_SPtrans[7][(t>>24)&0x3f]| \
-               des_SPtrans[0][(u    )&0x3f]| \
-               des_SPtrans[2][(u>> 8)&0x3f]| \
-               des_SPtrans[4][(u>>16)&0x3f]| \
-               des_SPtrans[6][(u>>24)&0x3f];
-
-/* This part is based on code that used to be in ecb_enc.c. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-
-static void des_encrypt(word32 l, word32 r, word32 *output, DESContext *ks, 
-                int encrypt)
-{
-  register word32 t,u;
-  register int i;
-  register word32 *s;
-
-  s = ks->key_schedule;
-
-  IP(l,r,t);
-  /* Things have been modified so that the initial rotate is
-   * done outside the loop.  This required the
-   * des_SPtrans values in sp.h to be rotated 1 bit to the right.
-   * One perl script later and things have a 5% speed up on a sparc2.
-   * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
-   * for pointing this out. */
-  t=(r<<1)|(r>>31);
-  r=(l<<1)|(l>>31);
-  l=t;
-  
-  /* I don't know if it is worth the effort of loop unrolling the
-   * inner loop */
-  if (encrypt)
-    {
-      for (i=0; i<32; i+=4)
-       {
-         D_ENCRYPT(l,r,i+0); /*  1 */
-         D_ENCRYPT(r,l,i+2); /*  2 */
-       }
-    }
-  else
-    {
-      for (i=30; i>0; i-=4)
-       {
-         D_ENCRYPT(l,r,i-0); /* 16 */
-         D_ENCRYPT(r,l,i-2); /* 15 */
-       }
-    }
-  l=(l>>1)|(l<<31);
-  r=(r>>1)|(r<<31);
-  
-  FP(r,l,t);
-  output[0]=l;
-  output[1]=r;
-}
+    L = rotl(L, 1);
+    R = rotl(R, 1);
 
-/* Code based on set_key.c. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-
-#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
-       (a)=(a)^(t)^(t>>(16-(n))))
-
-static void des_set_key(unsigned char *key, DESContext *ks)
-{
-  register word32 c, d, t, s, shifts;
-  register int i;
-  register word32 *schedule;
-
-  schedule = ks->key_schedule;
-
-  c = GET_32BIT_LSB_FIRST(key);
-  d = GET_32BIT_LSB_FIRST(key + 4);
-
-  /* I now do it in 47 simple operations :-)
-   * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
-   * for the inspiration. :-) */
-  PERM_OP(d,c,t,4,0x0f0f0f0f);
-  HPERM_OP(c,t,-2,0xcccc0000);
-  HPERM_OP(d,t,-2,0xcccc0000);
-  PERM_OP(d,c,t,1,0x55555555);
-  PERM_OP(c,d,t,8,0x00ff00ff);
-  PERM_OP(d,c,t,1,0x55555555);
-  d = ((d & 0xff) << 16) | (d & 0xff00) |
-    ((d >> 16) & 0xff) | ((c >> 4) & 0xf000000);
-  c&=0x0fffffff;
-  
-  shifts = 0x7efc;
-  for (i=0; i < 16; i++)
-    {
-      if (shifts & 1)
-       { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); }
-      else
-       { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); }
-      shifts >>= 1;
-      c&=0x0fffffff;
-      d&=0x0fffffff;
-
-      /* could be a few less shifts but I am to lazy at this
-       * point in time to investigate */
-
-      s = des_skb[0][ (c    )&0x3f                ] |
-         des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)] |
-         des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)] |
-         des_skb[3][((c>>20)&0x01)|((c>>21)&0x06)|((c>>22)&0x38)];
-
-      t = des_skb[4][ (d    )&0x3f                ] |
-         des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)] |
-         des_skb[6][ (d>>15)&0x3f                ] |
-         des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)];
-
-      /* table contained 0213 4657 */
-      *schedule++ = ((t << 16) | (s & 0xffff));
-      s = ((s >> 16) | (t & 0xffff0000));
-      *schedule++ = (s << 4) | (s >> 28);
-    }
+    L ^= f(R, sched->k0246[15], sched->k1357[15]);
+    R ^= f(L, sched->k0246[14], sched->k1357[14]);
+    L ^= f(R, sched->k0246[13], sched->k1357[13]);
+    R ^= f(L, sched->k0246[12], sched->k1357[12]);
+    L ^= f(R, sched->k0246[11], sched->k1357[11]);
+    R ^= f(L, sched->k0246[10], sched->k1357[10]);
+    L ^= f(R, sched->k0246[ 9], sched->k1357[ 9]);
+    R ^= f(L, sched->k0246[ 8], sched->k1357[ 8]);
+    L ^= f(R, sched->k0246[ 7], sched->k1357[ 7]);
+    R ^= f(L, sched->k0246[ 6], sched->k1357[ 6]);
+    L ^= f(R, sched->k0246[ 5], sched->k1357[ 5]);
+    R ^= f(L, sched->k0246[ 4], sched->k1357[ 4]);
+    L ^= f(R, sched->k0246[ 3], sched->k1357[ 3]);
+    R ^= f(L, sched->k0246[ 2], sched->k1357[ 2]);
+    L ^= f(R, sched->k0246[ 1], sched->k1357[ 1]);
+    R ^= f(L, sched->k0246[ 0], sched->k1357[ 0]);
+
+    L = rotl(L, 31);
+    R = rotl(R, 31);
+
+    swap = L; L = R; R = swap;
+
+    FP(L, R);
+
+    output[0] = L;
+    output[1] = R;
 }
 
-static void des_cbc_encrypt(DESContext *ks, unsigned char *iv,
-                    unsigned char *dest, const unsigned char *src,
-                    unsigned int len)
-{
-  word32 iv0, iv1, out[2];
-  unsigned int i;
-  
-  assert((len & 7) == 0);
-
-  iv0 = GET_32BIT_LSB_FIRST(iv);
-  iv1 = GET_32BIT_LSB_FIRST(iv + 4);
-  
-  for (i = 0; i < len; i += 8)
-    {
-      iv0 ^= GET_32BIT_LSB_FIRST(src + i);
-      iv1 ^= GET_32BIT_LSB_FIRST(src + i + 4);
-      des_encrypt(iv0, iv1, out, ks, 1);
-      iv0 = out[0];
-      iv1 = out[1];
-      PUT_32BIT_LSB_FIRST(dest + i, iv0);
-      PUT_32BIT_LSB_FIRST(dest + i + 4, iv1);
+#define GET_32BIT_MSB_FIRST(cp) \
+  (((unsigned long)(unsigned char)(cp)[3]) | \
+  ((unsigned long)(unsigned char)(cp)[2] << 8) | \
+  ((unsigned long)(unsigned char)(cp)[1] << 16) | \
+  ((unsigned long)(unsigned char)(cp)[0] << 24))
+
+#define PUT_32BIT_MSB_FIRST(cp, value) do { \
+  (cp)[3] = (value); \
+  (cp)[2] = (value) >> 8; \
+  (cp)[1] = (value) >> 16; \
+  (cp)[0] = (value) >> 24; } while (0)
+
+static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src,
+                            unsigned int len, DESContext *sched) {
+    word32 out[2], iv0, iv1;
+    unsigned int i;
+
+    assert((len & 7) == 0);
+
+    iv0 = sched->eiv0;
+    iv1 = sched->eiv1;
+    for (i = 0; i < len; i += 8) {
+        iv0 ^= GET_32BIT_MSB_FIRST(src); src += 4;
+        iv1 ^= GET_32BIT_MSB_FIRST(src); src += 4;
+        des_encipher(out, iv0, iv1, sched);
+        iv0 = out[0];
+        iv1 = out[1];
+        PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4;
+        PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4;
     }
-  PUT_32BIT_LSB_FIRST(iv, iv0);
-  PUT_32BIT_LSB_FIRST(iv + 4, iv1);
+    sched->eiv0 = iv0;
+    sched->eiv1 = iv1;
 }
 
-static void des_cbc_decrypt(DESContext *ks, unsigned char *iv,
-                    unsigned char *dest, const unsigned char *src,
-                    unsigned int len)
-{
-  word32 iv0, iv1, d0, d1, out[2];
-  unsigned int i;
-  
-  assert((len & 7) == 0);
-
-  iv0 = GET_32BIT_LSB_FIRST(iv);
-  iv1 = GET_32BIT_LSB_FIRST(iv + 4);
-  
-  for (i = 0; i < len; i += 8)
-    {
-      d0 = GET_32BIT_LSB_FIRST(src + i);
-      d1 = GET_32BIT_LSB_FIRST(src + i + 4);
-      des_encrypt(d0, d1, out, ks, 0);
-      iv0 ^= out[0];
-      iv1 ^= out[1];
-      PUT_32BIT_LSB_FIRST(dest + i, iv0);
-      PUT_32BIT_LSB_FIRST(dest + i + 4, iv1);
-      iv0 = d0;
-      iv1 = d1;
+static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src,
+                            unsigned int len, DESContext *sched) {
+    word32 out[2], iv0, iv1, xL, xR;
+    unsigned int i;
+
+    assert((len & 7) == 0);
+
+    iv0 = sched->div0;
+    iv1 = sched->div1;
+    for (i = 0; i < len; i += 8) {
+        xL = GET_32BIT_MSB_FIRST(src); src += 4;
+        xR = GET_32BIT_MSB_FIRST(src); src += 4;
+        des_decipher(out, xL, xR, sched);
+        iv0 ^= out[0];
+        iv1 ^= out[1];
+        PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4;
+        PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4;
+        iv0 = xL;
+        iv1 = xR;
     }
-  PUT_32BIT_LSB_FIRST(iv, iv0);
-  PUT_32BIT_LSB_FIRST(iv + 4, iv1);
+    sched->div0 = iv0;
+    sched->div1 = iv1;
 }
 
-static void des_3cbc_encrypt(DESContext *ks1, unsigned char *iv1, 
-                     DESContext *ks2, unsigned char *iv2,
-                     DESContext *ks3, unsigned char *iv3,
-                     unsigned char *dest, const unsigned char *src,
-                     unsigned int len)
-{
-  des_cbc_encrypt(ks1, iv1, dest, src, len);
-  des_cbc_decrypt(ks2, iv2, dest, dest, len);
-  des_cbc_encrypt(ks3, iv3, dest, dest, len);
+static void des_3cbc_encrypt(unsigned char *dest, const unsigned char *src,
+                             unsigned int len, DESContext *scheds) {
+    des_cbc_encrypt(dest, src, len, &scheds[0]);
+    des_cbc_decrypt(dest, src, len, &scheds[1]);
+    des_cbc_encrypt(dest, src, len, &scheds[2]);
 }
 
-static void des_3cbc_decrypt(DESContext *ks1, unsigned char *iv1, 
-                     DESContext *ks2, unsigned char *iv2,
-                     DESContext *ks3, unsigned char *iv3,
-                     unsigned char *dest, const unsigned char *src,
-                     unsigned int len)
-{
-  des_cbc_decrypt(ks3, iv3, dest, src, len);
-  des_cbc_encrypt(ks2, iv2, dest, dest, len);
-  des_cbc_decrypt(ks1, iv1, dest, dest, len);
+static void des_3cbc_decrypt(unsigned char *dest, const unsigned char *src,
+                             unsigned int len, DESContext *scheds) {
+    des_cbc_decrypt(dest, src, len, &scheds[2]);
+    des_cbc_encrypt(dest, src, len, &scheds[1]);
+    des_cbc_decrypt(dest, src, len, &scheds[0]);
 }
 
-DESContext ekey1, ekey2, ekey3;
-unsigned char eiv1[8], eiv2[8], eiv3[8];
-
-DESContext dkey1, dkey2, dkey3;
-unsigned char div1[8], div2[8], div3[8];
+DESContext keys[3];
 
 static void des3_sesskey(unsigned char *key) {
-    des_set_key(key, &ekey1);
-    des_set_key(key+8, &ekey2);
-    des_set_key(key+16, &ekey3);
-    memset(eiv1, 0, sizeof(eiv1));
-    memset(eiv2, 0, sizeof(eiv2));
-    memset(eiv3, 0, sizeof(eiv3));
-    des_set_key(key, &dkey1);
-    des_set_key(key+8, &dkey2);
-    des_set_key(key+16, &dkey3);
-    memset(div1, 0, sizeof(div1));
-    memset(div2, 0, sizeof(div2));
-    memset(div3, 0, sizeof(div3));
+    des_key_setup(GET_32BIT_MSB_FIRST(key),
+                  GET_32BIT_MSB_FIRST(key+4), &keys[0]);
+    des_key_setup(GET_32BIT_MSB_FIRST(key+8),
+                  GET_32BIT_MSB_FIRST(key+12), &keys[1]);
+    des_key_setup(GET_32BIT_MSB_FIRST(key+16),
+                  GET_32BIT_MSB_FIRST(key+20), &keys[2]);
     logevent("Initialised triple-DES encryption");
 }
 
 static void des3_encrypt_blk(unsigned char *blk, int len) {
-    des_3cbc_encrypt(&ekey1, eiv1, &ekey2, eiv2, &ekey3, eiv3, blk, blk, len);
+    des_3cbc_encrypt(blk, blk, len, keys);
 }
 
 static void des3_decrypt_blk(unsigned char *blk, int len) {
-    des_3cbc_decrypt(&dkey1, div1, &dkey2, div2, &dkey3, div3, blk, blk, len);
+    des_3cbc_decrypt(blk, blk, len, keys);
 }
 
 struct ssh_cipher ssh_3des = {
@@ -675,19 +548,17 @@ struct ssh_cipher ssh_3des = {
 };
 
 static void des_sesskey(unsigned char *key) {
-    des_set_key(key, &ekey1);
-    memset(eiv1, 0, sizeof(eiv1));
-    des_set_key(key, &dkey1);
-    memset(div1, 0, sizeof(div1));
+    des_key_setup(GET_32BIT_MSB_FIRST(key),
+                  GET_32BIT_MSB_FIRST(key+4), &keys[0]);
     logevent("Initialised single-DES encryption");
 }
 
 static void des_encrypt_blk(unsigned char *blk, int len) {
-    des_cbc_encrypt(&ekey1, eiv1, blk, blk, len);
+    des_cbc_encrypt(blk, blk, len, keys);
 }
 
 static void des_decrypt_blk(unsigned char *blk, int len) {
-    des_cbc_decrypt(&dkey1, div1, blk, blk, len);
+    des_cbc_decrypt(blk, blk, len, keys);
 }
 
 struct ssh_cipher ssh_des = {
@@ -695,67 +566,3 @@ struct ssh_cipher ssh_des = {
     des_encrypt_blk,
     des_decrypt_blk
 };
-
-#ifdef DES_TEST
-
-void des_encrypt_buf(DESContext *ks, unsigned char *out, 
-                    const unsigned char *in, int encrypt)
-{
-  word32 in0, in1, output[0];
-
-  in0 = GET_32BIT_LSB_FIRST(in);
-  in1 = GET_32BIT_LSB_FIRST(in + 4);
-  des_encrypt(in0, in1, output, ks, encrypt);
-  PUT_32BIT_LSB_FIRST(out, output[0]);
-  PUT_32BIT_LSB_FIRST(out + 4, output[1]);
-}
-
-int main(int ac, char **av)
-{
-  FILE *f;
-  char line[1024], *cp;
-  int i, value;
-  unsigned char key[8], data[8], result[8], output[8];
-  DESContext ks;
-
-  while (fgets(line, sizeof(line), stdin))
-    {
-      for (i = 0; i < 8; i++)
-       {
-         if (sscanf(line + 2 * i, "%02x", &value) != 1)
-           {
-             fprintf(stderr, "1st col, i = %d, line: %s", i, line);
-             exit(1);
-           }
-         key[i] = value;
-       }
-      for (i = 0; i < 8; i++)
-       {
-         if (sscanf(line + 2 * i + 17, "%02x", &value) != 1)
-           {
-             fprintf(stderr, "2nd col, i = %d, line: %s", i, line);
-             exit(1);
-           }
-         data[i] = value;
-       }
-      for (i = 0; i < 8; i++)
-       {
-         if (sscanf(line + 2 * i + 2*17, "%02x", &value) != 1)
-           {
-             fprintf(stderr, "3rd col, i = %d, line: %s", i, line);
-             exit(1);
-           }
-         result[i] = value;
-       }
-      des_set_key(key, &ks);
-      des_encrypt_buf(&ks, output, data, 1);
-      if (memcmp(output, result, 8) != 0)
-       fprintf(stderr, "Encrypt failed: %s", line);
-      des_encrypt_buf(&ks, output, result, 0);
-      if (memcmp(output, data, 8) != 0)
-       fprintf(stderr, "Decrypt failed: %s", line);
-    }
-  exit(0);
-}
-#endif /* DES_TEST */
-
index dd33d4f..fc400c2 100644 (file)
@@ -253,36 +253,35 @@ BEGIN
     LISTBOX IDN_LIST, 3, 3, 154, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL
 END
 
-IDD_LICENCEBOX DIALOG DISCARDABLE 50, 50, 226, 231
+IDD_LICENCEBOX DIALOG DISCARDABLE 50, 50, 226, 223
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "PuTTY Licence"
 FONT 8, "MS Sans Serif"
 BEGIN
-    DEFPUSHBUTTON "OK", IDOK, 98, 211, 44, 14
+    DEFPUSHBUTTON "OK", IDOK, 98, 203, 44, 14
 
-    LTEXT "Copyright \251 1997-9 Simon Tatham", 1000, 10, 10, 206, 8
-    LTEXT "Portions copyright Eric Young", 1100, 10, 18, 206, 8
+    LTEXT "Copyright \251 1997-2000 Simon Tatham", 1000, 10, 10, 206, 8
 
-    LTEXT "Permission is hereby granted, free of charge, to any person", 1002, 10, 34, 206, 8
-    LTEXT "obtaining a copy of this software and associated documentation", 1003, 10, 42, 206, 8
-    LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1004, 10, 50, 206, 8
-    LTEXT "including without limitation the rights to use, copy, modify, merge,", 1005, 10, 58, 206, 8
-    LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1006, 10, 66, 206, 8
-    LTEXT "and to permit persons to whom the Software is furnished to do so,", 1007, 10, 74, 206, 8
-    LTEXT "subject to the following conditions:", 1008, 10, 82, 206, 8
+    LTEXT "Permission is hereby granted, free of charge, to any person", 1002, 10, 26, 206, 8
+    LTEXT "obtaining a copy of this software and associated documentation", 1003, 10, 34, 206, 8
+    LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1004, 10, 42, 206, 8
+    LTEXT "including without limitation the rights to use, copy, modify, merge,", 1005, 10, 50, 206, 8
+    LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1006, 10, 58, 206, 8
+    LTEXT "and to permit persons to whom the Software is furnished to do so,", 1007, 10, 66, 206, 8
+    LTEXT "subject to the following conditions:", 1008, 10, 74, 206, 8
 
-    LTEXT "The above copyright notice and this permission notice shall be", 1010, 10, 98, 206, 8
-    LTEXT "included in all copies or substantial portions of the Software.", 1011, 10, 106, 206, 8
+    LTEXT "The above copyright notice and this permission notice shall be", 1010, 10, 90, 206, 8
+    LTEXT "included in all copies or substantial portions of the Software.", 1011, 10, 98, 206, 8
 
-    LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1013, 10, 122, 206, 8
-    LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1014, 10, 130, 206, 8
-    LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1015, 10, 138, 206, 8
-    LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1016, 10, 146, 206, 8
-    LTEXT "PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL", 1017, 10, 154, 206, 8
-    LTEXT "SIMON TATHAM BE LIABLE FOR ANY CLAIM, DAMAGES OR", 1018, 10, 162, 206, 8
-    LTEXT "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1019, 10, 170, 206, 8
-    LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1020, 10, 178, 206, 8
-    LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1021, 10, 186, 206, 8
-    LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1022, 10, 194, 206, 8
+    LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1013, 10, 114, 206, 8
+    LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1014, 10, 122, 206, 8
+    LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1015, 10, 130, 206, 8
+    LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1016, 10, 138, 206, 8
+    LTEXT "PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL", 1017, 10, 146, 206, 8
+    LTEXT "SIMON TATHAM BE LIABLE FOR ANY CLAIM, DAMAGES OR", 1018, 10, 154, 206, 8
+    LTEXT "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1019, 10, 162, 206, 8
+    LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1020, 10, 170, 206, 8
+    LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1021, 10, 178, 206, 8
+    LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1022, 10, 186, 206, 8
 
 END