mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 01:32:25 +00:00
Dimitry Andric spotted that DH gex with SHA-256 was overflowing a buffer.
Fixed, and added paranoia so that this shouldn't happen again. [originally from svn r6606] [this svn revision also touched putty-wishlist]
This commit is contained in:
parent
2cf27e43bb
commit
078c516a45
29
ssh.c
29
ssh.c
@ -708,7 +708,7 @@ struct ssh_tag {
|
|||||||
void *cs_comp_ctx, *sc_comp_ctx;
|
void *cs_comp_ctx, *sc_comp_ctx;
|
||||||
const struct ssh_kex *kex;
|
const struct ssh_kex *kex;
|
||||||
const struct ssh_signkey *hostkey;
|
const struct ssh_signkey *hostkey;
|
||||||
unsigned char v2_session_id[32];
|
unsigned char v2_session_id[SSH2_KEX_MAX_HASH_LEN];
|
||||||
int v2_session_id_len;
|
int v2_session_id_len;
|
||||||
void *kex_ctx;
|
void *kex_ctx;
|
||||||
|
|
||||||
@ -4964,7 +4964,10 @@ static int first_in_commasep_string(char *needle, char *haystack, int haylen)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* SSH-2 key creation method.
|
* SSH-2 key creation method.
|
||||||
|
* (Currently assumes 2 lots of any hash are sufficient to generate
|
||||||
|
* keys/IVs for any cipher/MAC. SSH2_MKKEY_ITERS documents this assumption.)
|
||||||
*/
|
*/
|
||||||
|
#define SSH2_MKKEY_ITERS (2)
|
||||||
static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H, char chr,
|
static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H, char chr,
|
||||||
unsigned char *keyspace)
|
unsigned char *keyspace)
|
||||||
{
|
{
|
||||||
@ -5011,7 +5014,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
|||||||
char *hostkeydata, *sigdata, *keystr, *fingerprint;
|
char *hostkeydata, *sigdata, *keystr, *fingerprint;
|
||||||
int hostkeylen, siglen;
|
int hostkeylen, siglen;
|
||||||
void *hkey; /* actual host key */
|
void *hkey; /* actual host key */
|
||||||
unsigned char exchange_hash[32];
|
unsigned char exchange_hash[SSH2_KEX_MAX_HASH_LEN];
|
||||||
int n_preferred_kex;
|
int n_preferred_kex;
|
||||||
const struct ssh_kexes *preferred_kex[KEX_MAX];
|
const struct ssh_kexes *preferred_kex[KEX_MAX];
|
||||||
int n_preferred_ciphers;
|
int n_preferred_ciphers;
|
||||||
@ -5064,7 +5067,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
|||||||
s->preferred_kex[s->n_preferred_kex++] =
|
s->preferred_kex[s->n_preferred_kex++] =
|
||||||
&ssh_diffiehellman_group1;
|
&ssh_diffiehellman_group1;
|
||||||
break;
|
break;
|
||||||
case CIPHER_WARN:
|
case KEX_WARN:
|
||||||
/* Flag for later. Don't bother if it's the last in
|
/* Flag for later. Don't bother if it's the last in
|
||||||
* the list. */
|
* the list. */
|
||||||
if (i < KEX_MAX - 1) {
|
if (i < KEX_MAX - 1) {
|
||||||
@ -5662,13 +5665,21 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
|||||||
* hash from the _first_ key exchange.
|
* hash from the _first_ key exchange.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned char keyspace[40];
|
unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS];
|
||||||
|
assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'C',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'C',keyspace);
|
||||||
|
assert((ssh->cscipher->keylen+7) / 8 <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);
|
ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'A',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'A',keyspace);
|
||||||
|
assert(ssh->cscipher->blksize <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);
|
ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'E',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'E',keyspace);
|
||||||
|
assert(ssh->csmac->len <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
|
ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
|
||||||
|
memset(keyspace, 0, sizeof(keyspace));
|
||||||
}
|
}
|
||||||
|
|
||||||
logeventf(ssh, "Initialised %.200s client->server encryption",
|
logeventf(ssh, "Initialised %.200s client->server encryption",
|
||||||
@ -5720,13 +5731,21 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
|||||||
* hash from the _first_ key exchange.
|
* hash from the _first_ key exchange.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned char keyspace[40];
|
unsigned char keyspace[SSH2_KEX_MAX_HASH_LEN * SSH2_MKKEY_ITERS];
|
||||||
|
assert(sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'D',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'D',keyspace);
|
||||||
|
assert((ssh->sccipher->keylen+7) / 8 <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);
|
ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'B',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'B',keyspace);
|
||||||
|
assert(ssh->sccipher->blksize <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
|
ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
|
||||||
ssh2_mkkey(ssh,s->K,s->exchange_hash,'F',keyspace);
|
ssh2_mkkey(ssh,s->K,s->exchange_hash,'F',keyspace);
|
||||||
|
assert(ssh->scmac->len <=
|
||||||
|
ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
|
||||||
ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
|
ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
|
||||||
|
memset(keyspace, 0, sizeof(keyspace));
|
||||||
}
|
}
|
||||||
logeventf(ssh, "Initialised %.200s server->client encryption",
|
logeventf(ssh, "Initialised %.200s server->client encryption",
|
||||||
ssh->sccipher->text_name);
|
ssh->sccipher->text_name);
|
||||||
|
3
ssh.h
3
ssh.h
@ -252,6 +252,9 @@ struct ssh2_userkey {
|
|||||||
char *comment; /* the key comment */
|
char *comment; /* the key comment */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* The maximum length of any hash algorithm used in kex. (bytes) */
|
||||||
|
#define SSH2_KEX_MAX_HASH_LEN (32) /* SHA-256 */
|
||||||
|
|
||||||
extern const struct ssh_cipher ssh_3des;
|
extern const struct ssh_cipher ssh_3des;
|
||||||
extern const struct ssh_cipher ssh_des;
|
extern const struct ssh_cipher ssh_des;
|
||||||
extern const struct ssh_cipher ssh_blowfish_ssh1;
|
extern const struct ssh_cipher ssh_blowfish_ssh1;
|
||||||
|
Loading…
Reference in New Issue
Block a user