mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Fix Blowfish-with-SSH2 combination, and enable user cipher
selection for SSH2 [originally from svn r606]
This commit is contained in:
parent
9291dfc7c5
commit
ea8d61f2d9
33
ssh.c
33
ssh.c
@ -142,10 +142,20 @@ enum { PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM };
|
||||
extern struct ssh_cipher ssh_3des;
|
||||
extern struct ssh_cipher ssh_3des_ssh2;
|
||||
extern struct ssh_cipher ssh_des;
|
||||
extern struct ssh_cipher ssh_blowfish;
|
||||
extern struct ssh_cipher ssh_blowfish_ssh1;
|
||||
extern struct ssh_cipher ssh_blowfish_ssh2;
|
||||
|
||||
/* for ssh 2; we miss out single-DES because it isn't supported */
|
||||
struct ssh_cipher *ciphers[] = { &ssh_3des_ssh2, &ssh_blowfish };
|
||||
/*
|
||||
* Ciphers for SSH2. We miss out single-DES because it isn't
|
||||
* supported; also 3DES and Blowfish are both done differently from
|
||||
* SSH1. (3DES uses outer chaining; Blowfish has the opposite
|
||||
* endianness and different-sized keys.)
|
||||
*
|
||||
* The first entry in this array is set up to be whatever the user
|
||||
* asks for as a cipher. Thereafter there is a fixed preference
|
||||
* order of fallback ciphers.
|
||||
*/
|
||||
struct ssh_cipher *ciphers[] = { NULL, &ssh_blowfish_ssh2, &ssh_3des_ssh2 };
|
||||
|
||||
extern struct ssh_kex ssh_diffiehellman;
|
||||
struct ssh_kex *kex_algs[] = { &ssh_diffiehellman };
|
||||
@ -1163,7 +1173,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
||||
|
||||
free(rsabuf);
|
||||
|
||||
cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish :
|
||||
cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
|
||||
cipher_type == SSH_CIPHER_DES ? &ssh_des :
|
||||
&ssh_3des;
|
||||
cipher->sesskey(session_key);
|
||||
@ -1780,6 +1790,21 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
crBegin;
|
||||
random_init();
|
||||
|
||||
/*
|
||||
* Set up the preferred cipher.
|
||||
*/
|
||||
if (cfg.cipher == CIPHER_BLOWFISH) {
|
||||
ciphers[0] = &ssh_blowfish_ssh2;
|
||||
} else if (cfg.cipher == CIPHER_DES) {
|
||||
logevent("Single DES not supported in SSH2; using 3DES");
|
||||
ciphers[0] = &ssh_3des_ssh2;
|
||||
} else if (cfg.cipher == CIPHER_3DES) {
|
||||
ciphers[0] = &ssh_3des_ssh2;
|
||||
} else {
|
||||
/* Shouldn't happen, but we do want to initialise to _something_. */
|
||||
ciphers[0] = &ssh_3des_ssh2;
|
||||
}
|
||||
|
||||
begin_key_exchange:
|
||||
/*
|
||||
* Construct and send our key exchange packet.
|
||||
|
112
sshblowf.c
112
sshblowf.c
@ -25,6 +25,18 @@ typedef struct {
|
||||
(cp)[2] = (value) >> 16; \
|
||||
(cp)[3] = (value) >> 24; } while (0)
|
||||
|
||||
#define GET_32BIT_MSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
|
||||
((unsigned long)(unsigned char)(cp)[1] << 16) | \
|
||||
((unsigned long)(unsigned char)(cp)[2] << 8) | \
|
||||
((unsigned long)(unsigned char)(cp)[3]))
|
||||
|
||||
#define PUT_32BIT_MSB_FIRST(cp, value) do { \
|
||||
(cp)[0] = (value) >> 24; \
|
||||
(cp)[1] = (value) >> 16; \
|
||||
(cp)[2] = (value) >> 8; \
|
||||
(cp)[3] = (value); } while (0)
|
||||
|
||||
/*
|
||||
* The Blowfish init data: hex digits of the fractional part of pi.
|
||||
* (ie pi as a hex fraction is 3.243F6A8885A308D3...)
|
||||
@ -287,8 +299,8 @@ static void blowfish_decrypt(word32 xL, word32 xR, word32 *output,
|
||||
output[1] = xL;
|
||||
}
|
||||
|
||||
static void blowfish_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
static void blowfish_lsb_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
@ -312,8 +324,8 @@ static void blowfish_encrypt_cbc(unsigned char *blk, int len,
|
||||
ctx->iv0 = iv0; ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
@ -337,6 +349,56 @@ static void blowfish_decrypt_cbc(unsigned char *blk, int len,
|
||||
ctx->iv0 = iv0; ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0; iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk+4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk+4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0; ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext *ctx) {
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0; iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk+4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk+4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0; ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_setkey(BlowfishContext *ctx,
|
||||
const unsigned char *key, short keybytes) {
|
||||
word32 *S0 = ctx->S0;
|
||||
@ -406,14 +468,14 @@ static void blowfish_sckey(unsigned char *key)
|
||||
|
||||
static void blowfish_csiv(unsigned char *key)
|
||||
{
|
||||
ectx.iv0 = GET_32BIT_LSB_FIRST(key);
|
||||
ectx.iv1 = GET_32BIT_LSB_FIRST(key+4);
|
||||
ectx.iv0 = GET_32BIT_MSB_FIRST(key);
|
||||
ectx.iv1 = GET_32BIT_MSB_FIRST(key+4);
|
||||
}
|
||||
|
||||
static void blowfish_sciv(unsigned char *key)
|
||||
{
|
||||
dctx.iv0 = GET_32BIT_LSB_FIRST(key);
|
||||
dctx.iv1 = GET_32BIT_LSB_FIRST(key+4);
|
||||
dctx.iv0 = GET_32BIT_MSB_FIRST(key);
|
||||
dctx.iv1 = GET_32BIT_MSB_FIRST(key+4);
|
||||
}
|
||||
|
||||
static void blowfish_sesskey(unsigned char *key)
|
||||
@ -425,22 +487,42 @@ static void blowfish_sesskey(unsigned char *key)
|
||||
logevent("Initialised Blowfish encryption");
|
||||
}
|
||||
|
||||
static void blowfish_encrypt_blk(unsigned char *blk, int len)
|
||||
static void blowfish_ssh1_encrypt_blk(unsigned char *blk, int len)
|
||||
{
|
||||
blowfish_encrypt_cbc(blk, len, &ectx);
|
||||
blowfish_lsb_encrypt_cbc(blk, len, &ectx);
|
||||
}
|
||||
|
||||
static void blowfish_decrypt_blk(unsigned char *blk, int len)
|
||||
static void blowfish_ssh1_decrypt_blk(unsigned char *blk, int len)
|
||||
{
|
||||
blowfish_decrypt_cbc(blk, len, &dctx);
|
||||
blowfish_lsb_decrypt_cbc(blk, len, &dctx);
|
||||
}
|
||||
|
||||
struct ssh_cipher ssh_blowfish = {
|
||||
static void blowfish_ssh2_encrypt_blk(unsigned char *blk, int len)
|
||||
{
|
||||
blowfish_msb_encrypt_cbc(blk, len, &ectx);
|
||||
}
|
||||
|
||||
static void blowfish_ssh2_decrypt_blk(unsigned char *blk, int len)
|
||||
{
|
||||
blowfish_msb_decrypt_cbc(blk, len, &dctx);
|
||||
}
|
||||
|
||||
struct ssh_cipher ssh_blowfish_ssh1 = {
|
||||
blowfish_sesskey,
|
||||
blowfish_csiv, blowfish_cskey,
|
||||
blowfish_sciv, blowfish_sckey,
|
||||
blowfish_encrypt_blk,
|
||||
blowfish_decrypt_blk,
|
||||
blowfish_ssh1_encrypt_blk,
|
||||
blowfish_ssh1_decrypt_blk,
|
||||
"blowfish-cbc",
|
||||
8
|
||||
};
|
||||
|
||||
struct ssh_cipher ssh_blowfish_ssh2 = {
|
||||
blowfish_sesskey,
|
||||
blowfish_csiv, blowfish_cskey,
|
||||
blowfish_sciv, blowfish_sckey,
|
||||
blowfish_ssh2_encrypt_blk,
|
||||
blowfish_ssh2_decrypt_blk,
|
||||
"blowfish-cbc",
|
||||
8
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user