X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/37508af4ab231b1fde58345f5237f3ee82803829..HEAD:/sshdes.c diff --git a/sshdes.c b/sshdes.c index 66e70416..03d2b3ae 100644 --- a/sshdes.c +++ b/sshdes.c @@ -1,778 +1,1031 @@ #include #include "ssh.h" -/* - -DES implementation; 1995 Tatu Ylonen - -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. +/* 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 + */ /* - * $Id: sshdes.c,v 1.2 1999/01/08 13:10:15 simon Exp $ - * $Log: sshdes.c,v $ - * Revision 1.2 1999/01/08 13:10:15 simon - * John Sullivan's patches plus more fixes: - * - Stop using the identifier `environ' as some platforms make it a macro - * - Fix silly error box at end of connection in FWHACK mode - * - Fix GPF on maximise-then-restore - * - Use SetCapture to allow drag-selecting outside the window - * - Correctly update window title when iconic and in win_name_always mode - * - * Revision 1.1.1.1 1996/02/18 21:38:11 ylo - * Imported ssh-1.2.13. - * - * Revision 1.2 1995/07/13 01:22:57 ylo - * Added cvs log. - * - * $Endlog$ + * Implementation details + * ---------------------- + * + * If you look at the code in this module, you'll find it looks + * nothing _like_ the above algorithm. Here I explain the + * differences... + * + * Key setup has not been heavily optimised here. We are not + * concerned with key agility: we aren't codebreakers. We don't + * mind a little delay (and it really is a little one; it may be a + * factor of five or so slower than it could be but it's still not + * an appreciable length of time) while setting up. The only tweaks + * in the key setup are ones which change the format of the key + * schedule to speed up the actual encryption. I'll describe those + * below. + * + * The first and most obvious optimisation is the S-boxes. Since + * each S-box always targets the same four bits in the final 32-bit + * word, so the output from (for example) S-box 0 must always be + * shifted left 28 bits, we can store the already-shifted outputs + * in the lookup tables. This reduces lookup-and-shift to lookup, + * so the S-box step is now just a question of ORing together eight + * table lookups. + * + * The permutation P is just a bit order change; it's invariant + * with respect to OR, in that P(x)|P(y) = P(x|y). Therefore, we + * can apply P to every entry of the S-box tables and then we don't + * have to do it in the code of f(). This yields a set of tables + * which might be called SP-boxes. + * + * The bit-selection function E is our next target. Note that E is + * immediately followed by the operation of splitting into 6-bit + * chunks. Examining the 6-bit chunks coming out of E we notice + * they're all contiguous within the word (speaking cyclically - + * the end two wrap round); so we can extract those bit strings + * individually rather than explicitly running E. This would yield + * code such as + * + * y |= SPboxes[0][ (rotl(R, 5) ^ top6bitsofK) & 0x3F ]; + * t |= SPboxes[1][ (rotl(R,11) ^ next6bitsofK) & 0x3F ]; + * + * and so on; and the key schedule preparation would have to + * provide each 6-bit chunk separately. + * + * Really we'd like to XOR in the key schedule element before + * looking up bit strings in R. This we can't do, naively, because + * the 6-bit strings we want overlap. But look at the strings: + * + * 3322222222221111111111 + * bit 10987654321098765432109876543210 + * + * box0 XXXXX X + * box1 XXXXXX + * box2 XXXXXX + * box3 XXXXXX + * box4 XXXXXX + * box5 XXXXXX + * box6 XXXXXX + * box7 X XXXXX + * + * The bit strings we need to XOR in for boxes 0, 2, 4 and 6 don't + * overlap with each other. Neither do the ones for boxes 1, 3, 5 + * and 7. So we could provide the key schedule in the form of two + * words that we can separately XOR into R, and then every S-box + * index is available as a (cyclically) contiguous 6-bit substring + * of one or the other of the results. + * + * The comments in Eric Young's libdes implementation point out + * that two of these bit strings require a rotation (rather than a + * simple shift) to extract. It's unavoidable that at least _one_ + * must do; but we can actually run the whole inner algorithm (all + * 16 rounds) rotated one bit to the left, so that what the `real' + * DES description sees as L=0x80000001 we see as L=0x00000003. + * This requires rotating all our SP-box entries one bit to the + * left, and rotating each word of the key schedule elements one to + * the left, and rotating L and R one bit left just after IP and + * one bit right again just before FP. And in each round we convert + * a rotate into a shift, so we've saved a few per cent. + * + * That's about it for the inner loop; the SP-box tables as listed + * below are what I've described here (the original S value, + * shifted to its final place in the input to P, run through P, and + * then rotated one bit left). All that remains is to optimise the + * initial permutation IP. + * + * IP is not an arbitrary permutation. It has the nice property + * that if you take any bit number, write it in binary (6 bits), + * permute those 6 bits and invert some of them, you get the final + * position of that bit. Specifically, the bit whose initial + * position is given (in binary) as fedcba ends up in position + * AcbFED (where a capital letter denotes the inverse of a bit). + * + * We have the 64-bit data in two 32-bit words L and R, where bits + * in L are those with f=1 and bits in R are those with f=0. We + * note that we can do a simple transformation: suppose we exchange + * the bits with f=1,c=0 and the bits with f=0,c=1. This will cause + * the bit fedcba to be in position cedfba - we've `swapped' bits c + * and f in the position of each bit! + * + * Better still, this transformation is easy. In the example above, + * bits in L with c=0 are bits 0x0F0F0F0F, and those in R with c=1 + * are 0xF0F0F0F0. So we can do + * + * difference = ((R >> 4) ^ L) & 0x0F0F0F0F + * R ^= (difference << 4) + * L ^= difference + * + * to perform the swap. Let's denote this by bitswap(4,0x0F0F0F0F). + * Also, we can invert the bit at the top just by exchanging L and + * R. So in a few swaps and a few of these bit operations we can + * do: + * + * Initially the position of bit fedcba is fedcba + * Swap L with R to make it Fedcba + * Perform bitswap( 4,0x0F0F0F0F) to make it cedFba + * Perform bitswap(16,0x0000FFFF) to make it ecdFba + * Swap L with R to make it EcdFba + * Perform bitswap( 2,0x33333333) to make it bcdFEa + * Perform bitswap( 8,0x00FF00FF) to make it dcbFEa + * Swap L with R to make it DcbFEa + * Perform bitswap( 1,0x55555555) to make it acbFED + * Swap L with R to make it AcbFED + * + * (In the actual code the four swaps are implicit: R and L are + * simply used the other way round in the first, second and last + * bitswap operations.) + * + * The final permutation is just the inverse of IP, so it can be + * performed by a similar set of operations. */ -typedef struct -{ - word32 key_schedule[32]; +typedef struct { + word32 k0246[16], k1357[16]; + word32 iv0, iv1; } DESContext; -/* 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 rotl(x, c) ( (x << c) | (x >> (32-c)) ) +#define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF) -/* - -DES implementation; 1995 Tatu Ylonen +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 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 void des_key_setup(word32 key_msw, word32 key_lsw, DESContext * sched) +{ -This implementation is distributed under the same terms. See -libdes-README, libdes-ARTISTIC, and libdes-COPYING for more -information. + 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 + }; + /* + * The bit numbers in the two lists below don't correspond to + * the ones in the above description of PC2, because in the + * above description C and D are concatenated so `bit 28' means + * bit 0 of C. In this implementation we're using the standard + * `bitsel' function above and C is in the second word, so bit + * 0 of C is addressed by writing `32' here. + */ + 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); + } -A description of the DES algorithm can be found in every modern book on -cryptography and data security, including the following: + sched->iv0 = sched->iv1 = 0; +} - Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. +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} +}; - Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to - Computer Security. Prentice-Hall, 1989. +#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)) + +static 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; +} - Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill, - 1994. +static void des_decipher(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[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(unsigned char *blk, + unsigned int len, DESContext * sched) +{ + word32 out[2], iv0, iv1; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = sched->iv0; + iv1 = sched->iv1; + for (i = 0; i < len; i += 8) { + iv0 ^= GET_32BIT_MSB_FIRST(blk); + iv1 ^= GET_32BIT_MSB_FIRST(blk + 4); + des_encipher(out, iv0, iv1, sched); + iv0 = out[0]; + iv1 = out[1]; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; + } + sched->iv0 = iv0; + sched->iv1 = iv1; +} -/* - * $Id: sshdes.c,v 1.2 1999/01/08 13:10:15 simon Exp $ - * $Log: sshdes.c,v $ - * Revision 1.2 1999/01/08 13:10:15 simon - * John Sullivan's patches plus more fixes: - * - Stop using the identifier `environ' as some platforms make it a macro - * - Fix silly error box at end of connection in FWHACK mode - * - Fix GPF on maximise-then-restore - * - Use SetCapture to allow drag-selecting outside the window - * - Correctly update window title when iconic and in win_name_always mode - * - * Revision 1.1.1.1 1996/02/18 21:38:11 ylo - * Imported ssh-1.2.13. - * - * Revision 1.2 1995/07/13 01:22:25 ylo - * Added cvs log. - * - * $Endlog$ - */ +static void des_cbc_decrypt(unsigned char *blk, + unsigned int len, DESContext * sched) +{ + word32 out[2], iv0, iv1, xL, xR; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = sched->iv0; + iv1 = sched->iv1; + for (i = 0; i < len; i += 8) { + xL = GET_32BIT_MSB_FIRST(blk); + xR = GET_32BIT_MSB_FIRST(blk + 4); + des_decipher(out, xL, xR, sched); + iv0 ^= out[0]; + iv1 ^= out[1]; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; + iv0 = xL; + iv1 = xR; + } + sched->iv0 = iv0; + sched->iv1 = iv1; +} -/* 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 } -}; +static void des_3cbc_encrypt(unsigned char *blk, + unsigned int len, DESContext * scheds) +{ + des_cbc_encrypt(blk, len, &scheds[0]); + des_cbc_decrypt(blk, len, &scheds[1]); + des_cbc_encrypt(blk, len, &scheds[2]); +} -/* 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<>(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; -} - -/* 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); +static void des_cbc3_encrypt(unsigned char *blk, + unsigned int len, DESContext * scheds) +{ + word32 out[2], iv0, iv1; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = scheds->iv0; + iv1 = scheds->iv1; + for (i = 0; i < len; i += 8) { + iv0 ^= GET_32BIT_MSB_FIRST(blk); + iv1 ^= GET_32BIT_MSB_FIRST(blk + 4); + des_encipher(out, iv0, iv1, &scheds[0]); + des_decipher(out, out[0], out[1], &scheds[1]); + des_encipher(out, out[0], out[1], &scheds[2]); + iv0 = out[0]; + iv1 = out[1]; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; } + scheds->iv0 = iv0; + scheds->iv1 = iv1; } -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); +static void des_3cbc_decrypt(unsigned char *blk, + unsigned int len, DESContext * scheds) +{ + des_cbc_decrypt(blk, len, &scheds[2]); + des_cbc_encrypt(blk, len, &scheds[1]); + des_cbc_decrypt(blk, len, &scheds[0]); +} + +static void des_cbc3_decrypt(unsigned char *blk, + unsigned int len, DESContext * scheds) +{ + word32 out[2], iv0, iv1, xL, xR; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = scheds->iv0; + iv1 = scheds->iv1; + for (i = 0; i < len; i += 8) { + xL = GET_32BIT_MSB_FIRST(blk); + xR = GET_32BIT_MSB_FIRST(blk + 4); + des_decipher(out, xL, xR, &scheds[2]); + des_encipher(out, out[0], out[1], &scheds[1]); + des_decipher(out, out[0], out[1], &scheds[0]); + iv0 ^= out[0]; + iv1 ^= out[1]; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; + iv0 = xL; + iv1 = xR; } - PUT_32BIT_LSB_FIRST(iv, iv0); - PUT_32BIT_LSB_FIRST(iv + 4, 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; + scheds->iv0 = iv0; + scheds->iv1 = iv1; +} + +static void des_sdctr3(unsigned char *blk, + unsigned int len, DESContext * scheds) +{ + word32 b[2], iv0, iv1, tmp; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = scheds->iv0; + iv1 = scheds->iv1; + for (i = 0; i < len; i += 8) { + des_encipher(b, iv0, iv1, &scheds[0]); + des_decipher(b, b[0], b[1], &scheds[1]); + des_encipher(b, b[0], b[1], &scheds[2]); + tmp = GET_32BIT_MSB_FIRST(blk); + PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]); + blk += 4; + tmp = GET_32BIT_MSB_FIRST(blk); + PUT_32BIT_MSB_FIRST(blk, tmp ^ b[1]); + blk += 4; + if ((iv1 = (iv1 + 1) & 0xffffffff) == 0) + iv0 = (iv0 + 1) & 0xffffffff; } - PUT_32BIT_LSB_FIRST(iv, iv0); - PUT_32BIT_LSB_FIRST(iv + 4, iv1); + scheds->iv0 = iv0; + scheds->iv1 = 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) +static void *des3_make_context(void) { - des_cbc_encrypt(ks1, iv1, dest, src, len); - des_cbc_decrypt(ks2, iv2, dest, dest, len); - des_cbc_encrypt(ks3, iv3, dest, dest, len); + return snewn(3, DESContext); } -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) +static void *des3_ssh1_make_context(void) { - des_cbc_decrypt(ks3, iv3, dest, src, len); - des_cbc_encrypt(ks2, iv2, dest, dest, len); - des_cbc_decrypt(ks1, iv1, dest, dest, len); + /* Need 3 keys for each direction, in SSH-1 */ + return snewn(6, DESContext); } -DESContext ekey1, ekey2, ekey3; -unsigned char eiv1[8], eiv2[8], eiv3[8]; +static void *des_make_context(void) +{ + return snew(DESContext); +} -DESContext dkey1, dkey2, dkey3; -unsigned char div1[8], div2[8], div3[8]; +static void *des_ssh1_make_context(void) +{ + /* Need one key for each direction, in SSH-1 */ + return snewn(2, DESContext); +} -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)); +static void des3_free_context(void *handle) /* used for both 3DES and DES */ +{ + sfree(handle); } -static void des3_encrypt_blk(unsigned char *blk, int len) { - des_3cbc_encrypt(&ekey1, eiv1, &ekey2, eiv2, &ekey3, eiv3, blk, blk, len); +static void des3_key(void *handle, unsigned char *key) +{ + DESContext *keys = (DESContext *) handle; + 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]); } -static void des3_decrypt_blk(unsigned char *blk, int len) { - des_3cbc_decrypt(&dkey1, div1, &dkey2, div2, &dkey3, div3, blk, blk, len); +static void des3_iv(void *handle, unsigned char *key) +{ + DESContext *keys = (DESContext *) handle; + keys[0].iv0 = GET_32BIT_MSB_FIRST(key); + keys[0].iv1 = GET_32BIT_MSB_FIRST(key + 4); } -struct ssh_cipher ssh_3des = { - des3_sesskey, - des3_encrypt_blk, - des3_decrypt_blk -}; +static void des_key(void *handle, unsigned char *key) +{ + DESContext *keys = (DESContext *) handle; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &keys[0]); +} -#ifdef DES_TEST +static void des3_sesskey(void *handle, unsigned char *key) +{ + DESContext *keys = (DESContext *) handle; + des3_key(keys, key); + des3_key(keys+3, key); +} -void des_encrypt_buf(DESContext *ks, unsigned char *out, - const unsigned char *in, int encrypt) +static void des3_encrypt_blk(void *handle, unsigned char *blk, int len) { - word32 in0, in1, output[0]; + DESContext *keys = (DESContext *) handle; + des_3cbc_encrypt(blk, len, keys); +} - 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]); +static void des3_decrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_3cbc_decrypt(blk, len, keys+3); } -int main(int ac, char **av) +static void des3_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) { - FILE *f; - char line[1024], *cp; - int i, value; - unsigned char key[8], data[8], result[8], output[8]; - DESContext ks; + DESContext *keys = (DESContext *) handle; + des_cbc3_encrypt(blk, len, keys); +} - 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; +static void des3_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_cbc3_decrypt(blk, len, keys); +} + +static void des3_ssh2_sdctr(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_sdctr3(blk, len, keys); +} + +static void des_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_cbc_encrypt(blk, len, keys); +} + +static void des_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_cbc_decrypt(blk, len, keys); +} + +void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) +{ + DESContext ourkeys[3]; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 8), + GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]); + des_3cbc_decrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); +} + +void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) +{ + DESContext ourkeys[3]; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 8), + GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]); + des_3cbc_encrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); +} + +void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, + unsigned char *blk, int len) +{ + DESContext ourkeys[3]; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 8), + GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 16), + GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]); + ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv); + ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4); + des_cbc3_decrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); +} + +void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, + unsigned char *blk, int len) +{ + DESContext ourkeys[3]; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 8), + GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 16), + GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]); + ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv); + ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4); + des_cbc3_encrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); +} + +static void des_keysetup_xdmauth(unsigned char *keydata, DESContext *dc) +{ + unsigned char key[8]; + int i, nbits, j; + unsigned int bits; + + bits = 0; + nbits = 0; + j = 0; + for (i = 0; i < 8; i++) { + if (nbits < 7) { + bits = (bits << 8) | keydata[j]; + nbits += 8; + j++; } - 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); + key[i] = (bits >> (nbits - 7)) << 1; + bits &= ~(0x7F << (nbits - 7)); + nbits -= 7; } - exit(0); + + des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4), dc); +} + +void des_encrypt_xdmauth(unsigned char *keydata, unsigned char *blk, int len) +{ + DESContext dc; + des_keysetup_xdmauth(keydata, &dc); + des_cbc_encrypt(blk, 24, &dc); +} + +void des_decrypt_xdmauth(unsigned char *keydata, unsigned char *blk, int len) +{ + DESContext dc; + des_keysetup_xdmauth(keydata, &dc); + des_cbc_decrypt(blk, 24, &dc); +} + +static const struct ssh2_cipher ssh_3des_ssh2 = { + des3_make_context, des3_free_context, des3_iv, des3_key, + des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, + "3des-cbc", + 8, 168, SSH_CIPHER_IS_CBC, "triple-DES CBC" +}; + +static const struct ssh2_cipher ssh_3des_ssh2_ctr = { + des3_make_context, des3_free_context, des3_iv, des3_key, + des3_ssh2_sdctr, des3_ssh2_sdctr, + "3des-ctr", + 8, 168, 0, "triple-DES SDCTR" +}; + +/* + * Single DES in SSH-2. "des-cbc" is marked as HISTORIC in + * RFC 4250, referring to + * FIPS-46-3. ("Single DES (i.e., DES) will be permitted + * for legacy systems only.") , but ssh.com support it and + * apparently aren't the only people to do so, so we sigh + * and implement it anyway. + */ +static const struct ssh2_cipher ssh_des_ssh2 = { + des_make_context, des3_free_context, des3_iv, des_key, + des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, + "des-cbc", + 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC" +}; + +static const struct ssh2_cipher ssh_des_sshcom_ssh2 = { + des_make_context, des3_free_context, des3_iv, des_key, + des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, + "des-cbc@ssh.com", + 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC" +}; + +static const struct ssh2_cipher *const des3_list[] = { + &ssh_3des_ssh2_ctr, + &ssh_3des_ssh2 +}; + +const struct ssh2_ciphers ssh2_3des = { + sizeof(des3_list) / sizeof(*des3_list), + des3_list +}; + +static const struct ssh2_cipher *const des_list[] = { + &ssh_des_ssh2, + &ssh_des_sshcom_ssh2 +}; + +const struct ssh2_ciphers ssh2_des = { + sizeof(des_list) / sizeof(*des_list), + des_list +}; + +const struct ssh_cipher ssh_3des = { + des3_ssh1_make_context, des3_free_context, des3_sesskey, + des3_encrypt_blk, des3_decrypt_blk, + 8, "triple-DES inner-CBC" +}; + +static void des_sesskey(void *handle, unsigned char *key) +{ + DESContext *keys = (DESContext *) handle; + des_key(keys, key); + des_key(keys+1, key); +} + +static void des_encrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_cbc_encrypt(blk, len, keys); } -#endif /* DES_TEST */ +static void des_decrypt_blk(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_cbc_decrypt(blk, len, keys+1); +} + +const struct ssh_cipher ssh_des = { + des_ssh1_make_context, des3_free_context, des_sesskey, + des_encrypt_blk, des_decrypt_blk, + 8, "single-DES CBC" +};