1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-18 03:20:59 -05:00

Merge the ssh1_cipher type into ssh2_cipher.

The aim of this reorganisation is to make it easier to test all the
ciphers in PuTTY in a uniform way. It was inconvenient that there were
two separate vtable systems for the ciphers used in SSH-1 and SSH-2
with different functionality.

Now there's only one type, called ssh_cipher. But really it's the old
ssh2_cipher, just renamed: I haven't made any changes to the API on
the SSH-2 side. Instead, I've removed ssh1_cipher completely, and
adapted the SSH-1 BPP to use the SSH-2 style API.

(The relevant differences are that ssh1_cipher encapsulated both the
sending and receiving directions in one object - so now ssh1bpp has to
make a separate cipher instance per direction - and that ssh1_cipher
automatically initialised the IV to all zeroes, which ssh1bpp now has
to do by hand.)

The previous ssh1_cipher vtable for single-DES has been removed
completely, because when converted into the new API it became
identical to the SSH-2 single-DES vtable; so now there's just one
vtable for DES-CBC which works in both protocols. The other two SSH-1
ciphers each had to stay separate, because 3DES is completely
different between SSH-1 and SSH-2 (three layers of CBC structure
versus one), and Blowfish varies in endianness and key length between
the two.

(Actually, while I'm here, I've only just noticed that the SSH-1
Blowfish cipher mis-describes itself in log messages as Blowfish-128.
In fact it passes the whole of the input key buffer, which has length
SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually
Blowfish-256, and has been all along!)
This commit is contained in:
Simon Tatham
2019-01-17 18:06:08 +00:00
parent 20930e7d0c
commit 986508a570
22 changed files with 465 additions and 611 deletions

View File

@ -17,7 +17,7 @@ struct ssh1_bpp_state {
int chunk;
PktIn *pktin;
ssh1_cipher *cipher;
ssh_cipher *cipher_in, *cipher_out;
struct crcda_ctx *crcda_ctx;
uint8_t iv[8]; /* for crcda */
@ -57,8 +57,10 @@ BinaryPacketProtocol *ssh1_bpp_new(LogContext *logctx)
static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s = container_of(bpp, struct ssh1_bpp_state, bpp);
if (s->cipher)
ssh1_cipher_free(s->cipher);
if (s->cipher_in)
ssh_cipher_free(s->cipher_in);
if (s->cipher_out)
ssh_cipher_free(s->cipher_out);
if (s->compctx)
ssh_compressor_free(s->compctx);
if (s->decompctx)
@ -70,18 +72,21 @@ static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
}
void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
const ssh1_cipheralg *cipher,
const ssh_cipheralg *cipher,
const void *session_key)
{
struct ssh1_bpp_state *s;
assert(bpp->vt == &ssh1_bpp_vtable);
s = container_of(bpp, struct ssh1_bpp_state, bpp);
assert(!s->cipher);
assert(!s->cipher_in);
assert(!s->cipher_out);
if (cipher) {
s->cipher = ssh1_cipher_new(cipher);
ssh1_cipher_sesskey(s->cipher, session_key);
s->cipher_in = ssh_cipher_new(cipher);
s->cipher_out = ssh_cipher_new(cipher);
ssh_cipher_setkey(s->cipher_in, session_key);
ssh_cipher_setkey(s->cipher_out, session_key);
assert(!s->crcda_ctx);
s->crcda_ctx = crcda_make_context();
@ -89,6 +94,10 @@ void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
bpp_logevent("Initialised %s encryption", cipher->text_name);
memset(s->iv, 0, sizeof(s->iv));
assert(cipher->blksize <= sizeof(s->iv));
ssh_cipher_setiv(s->cipher_in, s->iv);
ssh_cipher_setiv(s->cipher_out, s->iv);
}
}
@ -157,8 +166,8 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
BPP_READ(s->data, s->biglen);
if (s->cipher && detect_attack(s->crcda_ctx,
s->data, s->biglen, s->iv)) {
if (s->cipher_in && detect_attack(s->crcda_ctx,
s->data, s->biglen, s->iv)) {
ssh_sw_abort(s->bpp.ssh,
"Network attack (CRC compensation) detected!");
crStopV;
@ -168,8 +177,8 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
assert(s->biglen >= 8);
memcpy(s->iv, s->data + s->biglen - 8, sizeof(s->iv));
if (s->cipher)
ssh1_cipher_decrypt(s->cipher, s->data, s->biglen);
if (s->cipher_in)
ssh_cipher_decrypt(s->cipher_in, s->data, s->biglen);
s->realcrc = crc32_ssh1(make_ptrlen(s->data, s->biglen - 4));
s->gotcrc = GET_32BIT(s->data + s->biglen - 4);
@ -327,8 +336,8 @@ static void ssh1_bpp_format_packet(struct ssh1_bpp_state *s, PktOut *pkt)
PUT_32BIT(pkt->data + pktoffs + 4 + biglen - 4, crc);
PUT_32BIT(pkt->data + pktoffs, len);
if (s->cipher)
ssh1_cipher_encrypt(s->cipher, pkt->data + pktoffs + 4, biglen);
if (s->cipher_out)
ssh_cipher_encrypt(s->cipher_out, pkt->data + pktoffs + 4, biglen);
bufchain_add(s->bpp.out_raw, pkt->data + pktoffs,
biglen + 4); /* len(length+padding+type+data+CRC) */