mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-15 10:07:39 -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:
71
ssh2bpp.c
71
ssh2bpp.c
@ -11,7 +11,7 @@
|
||||
|
||||
struct ssh2_bpp_direction {
|
||||
unsigned long sequence;
|
||||
ssh2_cipher *cipher;
|
||||
ssh_cipher *cipher;
|
||||
ssh2_mac *mac;
|
||||
bool etm_mode;
|
||||
const ssh_compression_alg *pending_compression;
|
||||
@ -73,7 +73,7 @@ static void ssh2_bpp_free_outgoing_crypto(struct ssh2_bpp_state *s)
|
||||
* We must free the MAC before the cipher, because sometimes the
|
||||
* MAC is not actually separately allocated but just a different
|
||||
* facet of the same object as the cipher, in which case
|
||||
* ssh2_mac_free does nothing and ssh2_cipher_free does the actual
|
||||
* ssh2_mac_free does nothing and ssh_cipher_free does the actual
|
||||
* freeing. So if we freed the cipher first and then tried to
|
||||
* dereference the MAC's vtable pointer to find out how to free
|
||||
* that too, we'd be accessing freed memory.
|
||||
@ -81,7 +81,7 @@ static void ssh2_bpp_free_outgoing_crypto(struct ssh2_bpp_state *s)
|
||||
if (s->out.mac)
|
||||
ssh2_mac_free(s->out.mac);
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_free(s->out.cipher);
|
||||
ssh_cipher_free(s->out.cipher);
|
||||
if (s->out_comp)
|
||||
ssh_compressor_free(s->out_comp);
|
||||
}
|
||||
@ -92,7 +92,7 @@ static void ssh2_bpp_free_incoming_crypto(struct ssh2_bpp_state *s)
|
||||
if (s->in.mac)
|
||||
ssh2_mac_free(s->in.mac);
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_free(s->in.cipher);
|
||||
ssh_cipher_free(s->in.cipher);
|
||||
if (s->in_decomp)
|
||||
ssh_decompressor_free(s->in_decomp);
|
||||
}
|
||||
@ -109,7 +109,7 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
|
||||
|
||||
void ssh2_bpp_new_outgoing_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
|
||||
const ssh_compression_alg *compression, bool delayed_compression)
|
||||
{
|
||||
@ -120,16 +120,16 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
ssh2_bpp_free_outgoing_crypto(s);
|
||||
|
||||
if (cipher) {
|
||||
s->out.cipher = ssh2_cipher_new(cipher);
|
||||
ssh2_cipher_setkey(s->out.cipher, ckey);
|
||||
ssh2_cipher_setiv(s->out.cipher, iv);
|
||||
s->out.cipher = ssh_cipher_new(cipher);
|
||||
ssh_cipher_setkey(s->out.cipher, ckey);
|
||||
ssh_cipher_setiv(s->out.cipher, iv);
|
||||
|
||||
s->cbc_ignore_workaround = (
|
||||
(ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
(ssh_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
!(s->bpp.remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE));
|
||||
|
||||
bpp_logevent("Initialised %s outbound encryption",
|
||||
ssh2_cipher_alg(s->out.cipher)->text_name);
|
||||
ssh_cipher_alg(s->out.cipher)->text_name);
|
||||
} else {
|
||||
s->out.cipher = NULL;
|
||||
s->cbc_ignore_workaround = false;
|
||||
@ -143,7 +143,7 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
ssh2_mac_alg(s->out.mac)->text_name,
|
||||
etm_mode ? " (in ETM mode)" : "",
|
||||
(s->out.cipher &&
|
||||
ssh2_cipher_alg(s->out.cipher)->required_mac ?
|
||||
ssh_cipher_alg(s->out.cipher)->required_mac ?
|
||||
" (required by cipher)" : ""));
|
||||
} else {
|
||||
s->out.mac = NULL;
|
||||
@ -171,7 +171,7 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
|
||||
void ssh2_bpp_new_incoming_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
|
||||
const ssh_compression_alg *compression, bool delayed_compression)
|
||||
{
|
||||
@ -182,12 +182,12 @@ void ssh2_bpp_new_incoming_crypto(
|
||||
ssh2_bpp_free_incoming_crypto(s);
|
||||
|
||||
if (cipher) {
|
||||
s->in.cipher = ssh2_cipher_new(cipher);
|
||||
ssh2_cipher_setkey(s->in.cipher, ckey);
|
||||
ssh2_cipher_setiv(s->in.cipher, iv);
|
||||
s->in.cipher = ssh_cipher_new(cipher);
|
||||
ssh_cipher_setkey(s->in.cipher, ckey);
|
||||
ssh_cipher_setiv(s->in.cipher, iv);
|
||||
|
||||
bpp_logevent("Initialised %s inbound encryption",
|
||||
ssh2_cipher_alg(s->in.cipher)->text_name);
|
||||
ssh_cipher_alg(s->in.cipher)->text_name);
|
||||
} else {
|
||||
s->in.cipher = NULL;
|
||||
}
|
||||
@ -200,7 +200,7 @@ void ssh2_bpp_new_incoming_crypto(
|
||||
ssh2_mac_alg(s->in.mac)->text_name,
|
||||
etm_mode ? " (in ETM mode)" : "",
|
||||
(s->in.cipher &&
|
||||
ssh2_cipher_alg(s->in.cipher)->required_mac ?
|
||||
ssh_cipher_alg(s->in.cipher)->required_mac ?
|
||||
" (required by cipher)" : ""));
|
||||
} else {
|
||||
s->in.mac = NULL;
|
||||
@ -283,7 +283,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
s->maxlen = 0;
|
||||
s->length = 0;
|
||||
if (s->in.cipher)
|
||||
s->cipherblk = ssh2_cipher_alg(s->in.cipher)->blksize;
|
||||
s->cipherblk = ssh_cipher_alg(s->in.cipher)->blksize;
|
||||
else
|
||||
s->cipherblk = 8;
|
||||
if (s->cipherblk < 8)
|
||||
@ -291,7 +291,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
s->maclen = s->in.mac ? ssh2_mac_alg(s->in.mac)->len : 0;
|
||||
|
||||
if (s->in.cipher &&
|
||||
(ssh2_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
(ssh_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
s->in.mac && !s->in.etm_mode) {
|
||||
/*
|
||||
* When dealing with a CBC-mode cipher, we want to avoid the
|
||||
@ -333,8 +333,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
BPP_READ(s->buf + (s->packetlen + s->maclen), s->cipherblk);
|
||||
/* Decrypt one more block (a little further back in
|
||||
* the stream). */
|
||||
ssh2_cipher_decrypt(s->in.cipher,
|
||||
s->buf + s->packetlen, s->cipherblk);
|
||||
ssh_cipher_decrypt(s->in.cipher,
|
||||
s->buf + s->packetlen, s->cipherblk);
|
||||
|
||||
/* Feed that block to the MAC. */
|
||||
put_data(s->in.mac,
|
||||
@ -376,12 +376,12 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
BPP_READ(s->buf, 4);
|
||||
|
||||
/* Cipher supports length decryption, so do it */
|
||||
if (s->in.cipher && (ssh2_cipher_alg(s->in.cipher)->flags &
|
||||
if (s->in.cipher && (ssh_cipher_alg(s->in.cipher)->flags &
|
||||
SSH_CIPHER_SEPARATE_LENGTH)) {
|
||||
/* Keep the packet the same though, so the MAC passes */
|
||||
unsigned char len[4];
|
||||
memcpy(len, s->buf, 4);
|
||||
ssh2_cipher_decrypt_length(
|
||||
ssh_cipher_decrypt_length(
|
||||
s->in.cipher, len, 4, s->in.sequence);
|
||||
s->len = toint(GET_32BIT(len));
|
||||
} else {
|
||||
@ -430,7 +430,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
|
||||
/* Decrypt everything between the length field and the MAC. */
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_decrypt(
|
||||
ssh_cipher_decrypt(
|
||||
s->in.cipher, s->data + 4, s->packetlen - 4);
|
||||
} else {
|
||||
if (s->bufsize < s->cipherblk) {
|
||||
@ -445,8 +445,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
BPP_READ(s->buf, s->cipherblk);
|
||||
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_decrypt(
|
||||
s->in.cipher, s->buf, s->cipherblk);
|
||||
ssh_cipher_decrypt(s->in.cipher, s->buf, s->cipherblk);
|
||||
|
||||
/*
|
||||
* Now get the length figure.
|
||||
@ -488,7 +487,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
|
||||
/* Decrypt everything _except_ the MAC. */
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_decrypt(
|
||||
ssh_cipher_decrypt(
|
||||
s->in.cipher,
|
||||
s->data + s->cipherblk, s->packetlen - s->cipherblk);
|
||||
|
||||
@ -684,7 +683,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
pkt->downstream_id, pkt->additional_log_text);
|
||||
}
|
||||
|
||||
cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8;
|
||||
cipherblk = s->out.cipher ? ssh_cipher_alg(s->out.cipher)->blksize : 8;
|
||||
cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
|
||||
|
||||
if (s->out_comp) {
|
||||
@ -733,9 +732,9 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
|
||||
/* Encrypt length if the scheme requires it */
|
||||
if (s->out.cipher &&
|
||||
(ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) {
|
||||
ssh2_cipher_encrypt_length(s->out.cipher, pkt->data, 4,
|
||||
s->out.sequence);
|
||||
(ssh_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) {
|
||||
ssh_cipher_encrypt_length(s->out.cipher, pkt->data, 4,
|
||||
s->out.sequence);
|
||||
}
|
||||
|
||||
put_padding(pkt, maclen, 0);
|
||||
@ -745,8 +744,8 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
* OpenSSH-defined encrypt-then-MAC protocol.
|
||||
*/
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_encrypt(s->out.cipher,
|
||||
pkt->data + 4, origlen + padding - 4);
|
||||
ssh_cipher_encrypt(s->out.cipher,
|
||||
pkt->data + 4, origlen + padding - 4);
|
||||
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
} else {
|
||||
@ -757,7 +756,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
|
||||
ssh_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
|
||||
}
|
||||
|
||||
s->out.sequence++; /* whether or not we MACed */
|
||||
@ -791,7 +790,7 @@ static void ssh2_bpp_format_packet(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
int block, length;
|
||||
PktOut *ignore_pkt;
|
||||
|
||||
block = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 0;
|
||||
block = s->out.cipher ? ssh_cipher_alg(s->out.cipher)->blksize : 0;
|
||||
if (block < 8)
|
||||
block = 8;
|
||||
length = pkt->length;
|
||||
@ -874,7 +873,7 @@ static void ssh2_bpp_handle_output(BinaryPacketProtocol *bpp)
|
||||
* from out_raw).
|
||||
*/
|
||||
if (bufchain_size(s->bpp.out_raw) <
|
||||
(ssh2_cipher_alg(s->out.cipher)->blksize +
|
||||
(ssh_cipher_alg(s->out.cipher)->blksize +
|
||||
ssh2_mac_alg(s->out.mac)->len)) {
|
||||
/*
|
||||
* There's less data in out_raw than the MAC size plus the
|
||||
|
Reference in New Issue
Block a user