1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Now that we've got at least some SDCTR modes working (and aes256-ctr is our

default preferred cipher), add code to inject SSH_MSG_IGNOREs to randomise
the IV when using CBC-mode ciphers.  Each cipher has a flag to indicate
whether it needs this workaround, and the SSH packet output maze has gained
some extra complexity to implement it.

[originally from svn r5659]
This commit is contained in:
Ben Harris 2005-04-23 16:22:51 +00:00
parent b28330fc35
commit f2b0335c48
6 changed files with 48 additions and 19 deletions

35
ssh.c
View File

@ -1797,8 +1797,19 @@ static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)
* ssh2_pkt_send() or ssh2_pkt_defer() either go straight to one of * ssh2_pkt_send() or ssh2_pkt_defer() either go straight to one of
* these or get queued, and then when the queue is later emptied * these or get queued, and then when the queue is later emptied
* the packets are all passed to defer_noqueue(). * the packets are all passed to defer_noqueue().
*
* When using a CBC-mode cipher, it's necessary to ensure that an
* attacker can't provide data to be encrypted using an IV that they
* know. We ensure this by prefixing each packet that might contain
* user data with an SSH_MSG_IGNORE. This is done using the deferral
* mechanism, so in this case send_noqueue() ends up redirecting to
* defer_noqueue(). If you don't like this inefficiency, don't use
* CBC.
*/ */
static void ssh2_pkt_defer_noqueue(Ssh, struct Packet *, int);
static void ssh_pkt_defersend(Ssh);
/* /*
* Send an SSH-2 packet immediately, without queuing or deferring. * Send an SSH-2 packet immediately, without queuing or deferring.
*/ */
@ -1806,6 +1817,12 @@ static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)
{ {
int len; int len;
int backlog; int backlog;
if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) {
/* We need to send two packets, so use the deferral mechanism. */
ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
ssh_pkt_defersend(ssh);
return;
}
len = ssh2_pkt_construct(ssh, pkt); len = ssh2_pkt_construct(ssh, pkt);
backlog = sk_write(ssh->s, (char *)pkt->data, len); backlog = sk_write(ssh->s, (char *)pkt->data, len);
if (backlog > SSH_MAX_BACKLOG) if (backlog > SSH_MAX_BACKLOG)
@ -1823,9 +1840,19 @@ static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)
/* /*
* Defer an SSH-2 packet. * Defer an SSH-2 packet.
*/ */
static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt) static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt, int noignore)
{ {
int len = ssh2_pkt_construct(ssh, pkt); int len;
if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) &&
ssh->deferred_len == 0 && !noignore) {
/*
* Interpose an SSH_MSG_IGNORE to ensure that user data don't
* get encrypted with a known IV.
*/
struct Packet *ipkt = ssh2_pkt_init(SSH2_MSG_IGNORE);
ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE);
}
len = ssh2_pkt_construct(ssh, pkt);
if (ssh->deferred_len + len > ssh->deferred_size) { if (ssh->deferred_len + len > ssh->deferred_size) {
ssh->deferred_size = ssh->deferred_len + len + 128; ssh->deferred_size = ssh->deferred_len + len + 128;
ssh->deferred_send_data = sresize(ssh->deferred_send_data, ssh->deferred_send_data = sresize(ssh->deferred_send_data,
@ -1875,7 +1902,7 @@ static void ssh2_pkt_defer(Ssh ssh, struct Packet *pkt)
if (ssh->queueing) if (ssh->queueing)
ssh2_pkt_queue(ssh, pkt); ssh2_pkt_queue(ssh, pkt);
else else
ssh2_pkt_defer_noqueue(ssh, pkt); ssh2_pkt_defer_noqueue(ssh, pkt, FALSE);
} }
#endif #endif
@ -1923,7 +1950,7 @@ static void ssh2_pkt_queuesend(Ssh ssh)
assert(!ssh->queueing); assert(!ssh->queueing);
for (i = 0; i < ssh->queuelen; i++) for (i = 0; i < ssh->queuelen; i++)
ssh2_pkt_defer_noqueue(ssh, ssh->queue[i]); ssh2_pkt_defer_noqueue(ssh, ssh->queue[i], FALSE);
ssh->queuelen = 0; ssh->queuelen = 0;
ssh_pkt_defersend(ssh); ssh_pkt_defersend(ssh);

2
ssh.h
View File

@ -154,6 +154,8 @@ struct ssh2_cipher {
char *name; char *name;
int blksize; int blksize;
int keylen; int keylen;
unsigned int flags;
#define SSH_CIPHER_IS_CBC 1
char *text_name; char *text_name;
}; };

View File

@ -1173,49 +1173,49 @@ static const struct ssh2_cipher ssh_aes128_ctr = {
aes_make_context, aes_free_context, aes_iv, aes128_key, aes_make_context, aes_free_context, aes_iv, aes128_key,
aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr,
"aes128-ctr", "aes128-ctr",
16, 128, "AES-128 SDCTR" 16, 128, 0, "AES-128 SDCTR"
}; };
static const struct ssh2_cipher ssh_aes192_ctr = { static const struct ssh2_cipher ssh_aes192_ctr = {
aes_make_context, aes_free_context, aes_iv, aes192_key, aes_make_context, aes_free_context, aes_iv, aes192_key,
aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr,
"aes192-ctr", "aes192-ctr",
16, 192, "AES-192 SDCTR" 16, 192, 0, "AES-192 SDCTR"
}; };
static const struct ssh2_cipher ssh_aes256_ctr = { static const struct ssh2_cipher ssh_aes256_ctr = {
aes_make_context, aes_free_context, aes_iv, aes256_key, aes_make_context, aes_free_context, aes_iv, aes256_key,
aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr, aes_ssh2_sdctr,
"aes256-ctr", "aes256-ctr",
16, 256, "AES-256 SDCTR" 16, 256, 0, "AES-256 SDCTR"
}; };
static const struct ssh2_cipher ssh_aes128 = { static const struct ssh2_cipher ssh_aes128 = {
aes_make_context, aes_free_context, aes_iv, aes128_key, aes_make_context, aes_free_context, aes_iv, aes128_key,
aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
"aes128-cbc", "aes128-cbc",
16, 128, "AES-128 CBC" 16, 128, SSH_CIPHER_IS_CBC, "AES-128 CBC"
}; };
static const struct ssh2_cipher ssh_aes192 = { static const struct ssh2_cipher ssh_aes192 = {
aes_make_context, aes_free_context, aes_iv, aes192_key, aes_make_context, aes_free_context, aes_iv, aes192_key,
aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
"aes192-cbc", "aes192-cbc",
16, 192, "AES-192 CBC" 16, 192, SSH_CIPHER_IS_CBC, "AES-192 CBC"
}; };
static const struct ssh2_cipher ssh_aes256 = { static const struct ssh2_cipher ssh_aes256 = {
aes_make_context, aes_free_context, aes_iv, aes256_key, aes_make_context, aes_free_context, aes_iv, aes256_key,
aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
"aes256-cbc", "aes256-cbc",
16, 256, "AES-256 CBC" 16, 256, SSH_CIPHER_IS_CBC, "AES-256 CBC"
}; };
static const struct ssh2_cipher ssh_rijndael_lysator = { static const struct ssh2_cipher ssh_rijndael_lysator = {
aes_make_context, aes_free_context, aes_iv, aes256_key, aes_make_context, aes_free_context, aes_iv, aes256_key,
aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
"rijndael-cbc@lysator.liu.se", "rijndael-cbc@lysator.liu.se",
16, 256, "AES-256 CBC" 16, 256, SSH_CIPHER_IS_CBC, "AES-256 CBC"
}; };
static const struct ssh2_cipher *const aes_list[] = { static const struct ssh2_cipher *const aes_list[] = {

View File

@ -102,14 +102,14 @@ const struct ssh2_cipher ssh_arcfour128_ssh2 = {
arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key, arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key,
arcfour_block, arcfour_block, arcfour_block, arcfour_block,
"arcfour128-draft-00@putty.projects.tartarus.org", "arcfour128-draft-00@putty.projects.tartarus.org",
1, 128, "Arcfour-128" 1, 128, 0, "Arcfour-128"
}; };
const struct ssh2_cipher ssh_arcfour256_ssh2 = { const struct ssh2_cipher ssh_arcfour256_ssh2 = {
arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key, arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key,
arcfour_block, arcfour_block, arcfour_block, arcfour_block,
"arcfour256-draft-00@putty.projects.tartarus.org", "arcfour256-draft-00@putty.projects.tartarus.org",
1, 256, "Arcfour-256" 1, 256, 0, "Arcfour-256"
}; };
static const struct ssh2_cipher *const arcfour_list[] = { static const struct ssh2_cipher *const arcfour_list[] = {

View File

@ -573,7 +573,7 @@ static const struct ssh2_cipher ssh_blowfish_ssh2 = {
blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish_key, blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish_key,
blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk, blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk,
"blowfish-cbc", "blowfish-cbc",
8, 128, "Blowfish-128 CBC" 8, 128, SSH_CIPHER_IS_CBC, "Blowfish-128 CBC"
}; };
#ifdef ENABLE_BLOWFISH_SSH2_CTR #ifdef ENABLE_BLOWFISH_SSH2_CTR
@ -581,7 +581,7 @@ static const struct ssh2_cipher ssh_blowfish_ssh2_ctr = {
blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish256_key, blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish256_key,
blowfish_ssh2_sdctr, blowfish_ssh2_sdctr, blowfish_ssh2_sdctr, blowfish_ssh2_sdctr,
"blowfish-ctr", "blowfish-ctr",
8, 256, "Blowfish-256 SDCTR" 8, 256, 0, "Blowfish-256 SDCTR"
}; };
#endif #endif

View File

@ -965,7 +965,7 @@ static const struct ssh2_cipher ssh_3des_ssh2 = {
des3_make_context, des3_free_context, des3_iv, des3_key, des3_make_context, des3_free_context, des3_iv, des3_key,
des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk,
"3des-cbc", "3des-cbc",
8, 168, "triple-DES CBC" 8, 168, SSH_CIPHER_IS_CBC, "triple-DES CBC"
}; };
#ifdef ENABLE_3DES_SSH2_CTR #ifdef ENABLE_3DES_SSH2_CTR
@ -973,7 +973,7 @@ static const struct ssh2_cipher ssh_3des_ssh2_ctr = {
des3_make_context, des3_free_context, des3_iv, des3_key, des3_make_context, des3_free_context, des3_iv, des3_key,
des3_ssh2_sdctr, des3_ssh2_sdctr, des3_ssh2_sdctr, des3_ssh2_sdctr,
"3des-ctr", "3des-ctr",
8, 168, "triple-DES SDCTR" 8, 168, 0, "triple-DES SDCTR"
}; };
#endif #endif
@ -989,14 +989,14 @@ static const struct ssh2_cipher ssh_des_ssh2 = {
des_make_context, des3_free_context, des3_iv, des_key, des_make_context, des3_free_context, des3_iv, des_key,
des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk,
"des-cbc", "des-cbc",
8, 56, "single-DES CBC" 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC"
}; };
static const struct ssh2_cipher ssh_des_sshcom_ssh2 = { static const struct ssh2_cipher ssh_des_sshcom_ssh2 = {
des_make_context, des3_free_context, des3_iv, des_key, des_make_context, des3_free_context, des3_iv, des_key,
des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk,
"des-cbc@ssh.com", "des-cbc@ssh.com",
8, 56, "single-DES CBC" 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC"
}; };
/* /*