From 0183b2423868df18b2297c9052854e5a7db79425 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 25 Oct 2002 12:58:21 +0000 Subject: [PATCH] SSH CRC attack detector now uses a dynamically allocated context. git-svn-id: svn://svn.tartarus.org/sgt/putty@2132 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 8 +++++++- ssh.h | 5 ++++- sshcrcda.c | 52 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/ssh.c b/ssh.c index 9689fd24..677ff870 100644 --- a/ssh.c +++ b/ssh.c @@ -560,6 +560,7 @@ struct ssh_tag { int remote_bugs; const struct ssh_cipher *cipher; void *v1_cipher_ctx; + void *crcda_ctx; const struct ssh2_cipher *cscipher, *sccipher; void *cs_cipher_ctx, *sc_cipher_ctx; const struct ssh_mac *csmac, *scmac; @@ -809,7 +810,8 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen) st->to_read -= st->chunk; } - if (ssh->cipher && detect_attack(ssh->pktin.data, st->biglen, NULL)) { + if (ssh->cipher && detect_attack(ssh->crcda_ctx, ssh->pktin.data, + st->biglen, NULL)) { bombout(("Network attack (CRC compensation) detected!")); crReturn(0); } @@ -2377,6 +2379,9 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) logevent(buf); } + ssh->crcda_ctx = crcda_make_context(); + logevent("Installing CRC compensation attack detector"); + crWaitUntil(ispkt); if (ssh->pktin.type != SSH1_SMSG_SUCCESS) { @@ -5801,6 +5806,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh->s = NULL; ssh->cipher = NULL; ssh->v1_cipher_ctx = NULL; + ssh->crcda_ctx = NULL; ssh->cscipher = NULL; ssh->cs_cipher_ctx = NULL; ssh->sccipher = NULL; diff --git a/ssh.h b/ssh.h index 28dd6dd1..bf57b8fa 100644 --- a/ssh.h +++ b/ssh.h @@ -75,7 +75,10 @@ unsigned long crc32(const void *s, size_t len); unsigned long crc32_update(unsigned long crc_input, const void *s, size_t len); /* SSH CRC compensation attack detector */ -int detect_attack(unsigned char *buf, uint32 len, unsigned char *IV); +void *crcda_make_context(void); +void crcda_free_context(void *handle); +int detect_attack(void *handle, unsigned char *buf, uint32 len, + unsigned char *IV); typedef struct { uint32 h[4]; diff --git a/sshcrcda.c b/sshcrcda.c index 7b683be9..28210209 100644 --- a/sshcrcda.c +++ b/sshcrcda.c @@ -56,6 +56,24 @@ typedef unsigned short uint16; uchar ONE[4] = { 1, 0, 0, 0 }; uchar ZERO[4] = { 0, 0, 0, 0 }; +struct crcda_ctx { + uint16 *h; + uint32 n; +}; + +void *crcda_make_context(void) +{ + struct crcda_ctx *ret = smalloc(sizeof(struct crcda_ctx)); + ret->h = NULL; + ret->n = HASH_MINSIZE / HASH_ENTRYSIZE; + return ret; +} + +void crcda_free_context(void *handle) +{ + sfree(handle); +} + static void crc_update(uint32 *a, void *b) { *a = crc32_update(*a, b, 4); @@ -85,10 +103,9 @@ static int check_crc(uchar *S, uchar *buf, uint32 len, uchar *IV) } /* Detect a crc32 compensation attack on a packet */ -int detect_attack(uchar *buf, uint32 len, uchar *IV) +int detect_attack(void *handle, uchar *buf, uint32 len, uchar *IV) { - static uint16 *h = (uint16 *) NULL; - static uint32 n = HASH_MINSIZE / HASH_ENTRYSIZE; + struct crcda_ctx *ctx = (struct crcda_ctx *)handle; register uint32 i, j; uint32 l; register uchar *c; @@ -96,17 +113,16 @@ int detect_attack(uchar *buf, uint32 len, uchar *IV) assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || len % SSH_BLOCKSIZE != 0)); - for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) + for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) ; - if (h == NULL) { - logevent("Installing CRC compensation attack detector"); - n = l; - h = (uint16 *) smalloc(n * HASH_ENTRYSIZE); + if (ctx->h == NULL) { + ctx->n = l; + ctx->h = (uint16 *) smalloc(ctx->n * HASH_ENTRYSIZE); } else { - if (l > n) { - n = l; - h = (uint16 *) srealloc(h, n * HASH_ENTRYSIZE); + if (l > ctx->n) { + ctx->n = l; + ctx->h = (uint16 *) srealloc(ctx->h, ctx->n * HASH_ENTRYSIZE); } } @@ -129,29 +145,29 @@ int detect_attack(uchar *buf, uint32 len, uchar *IV) } return 0; /* ok */ } - memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE); + memset(ctx->h, HASH_UNUSEDCHAR, ctx->n * HASH_ENTRYSIZE); if (IV) - h[HASH(IV) & (n - 1)] = HASH_IV; + ctx->h[HASH(IV) & (ctx->n - 1)] = HASH_IV; for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { - for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; - i = (i + 1) & (n - 1)) { - if (h[i] == HASH_IV) { + for (i = HASH(c) & (ctx->n - 1); ctx->h[i] != HASH_UNUSED; + i = (i + 1) & (ctx->n - 1)) { + if (ctx->h[i] == HASH_IV) { if (!CMP(c, IV)) { if (check_crc(c, buf, len, IV)) return 1; /* attack detected */ else break; } - } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) { + } else if (!CMP(c, buf + ctx->h[i] * SSH_BLOCKSIZE)) { if (check_crc(c, buf, len, IV)) return 1; /* attack detected */ else break; } } - h[i] = j; + ctx->h[i] = j; } return 0; /* ok */ } -- 2.11.0