Annotation of src/usr.bin/ssh/deattack.c, Revision 1.1
1.1 ! dugsong 1: /*
! 2: * $Id: deattack.c,v 1.9 1998/06/27 00:02:22 futo Exp $ Cryptographic attack
! 3: * detector for ssh - source code (C)1998 CORE-SDI, Buenos Aires Argentina
! 4: * Ariel Futoransky(futo@core-sdi.com) <http://www.core-sdi.com>
! 5: */
! 6:
! 7: #include "includes.h"
! 8: #include "deattack.h"
! 9: #include "ssh.h"
! 10: #include "getput.h"
! 11: #include "xmalloc.h"
! 12:
! 13: /* SSH Constants */
! 14: #define SSH_MAXBLOCKS (32 * 1024)
! 15: #define SSH_BLOCKSIZE (8)
! 16:
! 17: /* Hashing constants */
! 18: #define HASH_MINSIZE (8 * 1024)
! 19: #define HASH_ENTRYSIZE (2)
! 20: #define HASH_FACTOR(x) ((x)*3/2)
! 21: #define HASH_UNUSEDCHAR (0xff)
! 22: #define HASH_UNUSED (0xffff)
! 23: #define HASH_IV (0xfffe)
! 24:
! 25: #define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
! 26:
! 27:
! 28: /* Hash function (Input keys are cipher results) */
! 29: #define HASH(x) GET_32BIT(x)
! 30:
! 31: #define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
! 32:
! 33:
! 34: void
! 35: crc_update(u_int32_t * a, u_int32_t b)
! 36: {
! 37: b ^= *a;
! 38: *a = crc32((unsigned char *) &b, sizeof(b));
! 39: }
! 40:
! 41: /*
! 42: check_crc
! 43: detects if a block is used in a particular pattern
! 44: */
! 45:
! 46: int
! 47: check_crc(unsigned char *S, unsigned char *buf, u_int32_t len, unsigned char *IV)
! 48: {
! 49: u_int32_t crc;
! 50: unsigned char *c;
! 51:
! 52: crc = 0;
! 53: if (IV && !CMP(S, IV))
! 54: {
! 55: crc_update(&crc, 1);
! 56: crc_update(&crc, 0);
! 57: }
! 58: for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
! 59: {
! 60: if (!CMP(S, c))
! 61: {
! 62: crc_update(&crc, 1);
! 63: crc_update(&crc, 0);
! 64: } else
! 65: {
! 66: crc_update(&crc, 0);
! 67: crc_update(&crc, 0);
! 68: }
! 69: }
! 70:
! 71: return (crc == 0);
! 72: }
! 73:
! 74:
! 75: /*
! 76: detect_attack
! 77: Detects a crc32 compensation attack on a packet
! 78: */
! 79: int
! 80: detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
! 81: {
! 82: static u_int16_t *h = (u_int16_t *) NULL;
! 83: static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
! 84: register u_int32_t i, j;
! 85: u_int32_t l;
! 86: register unsigned char *c;
! 87: unsigned char *d;
! 88:
! 89:
! 90: assert(len <= (SSH_MAXBLOCKS * SSH_BLOCKSIZE));
! 91: assert(len % SSH_BLOCKSIZE == 0);
! 92:
! 93: for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2);
! 94:
! 95: if (h == NULL)
! 96: {
! 97: debug("Installing crc compensation attack detector.");
! 98: n = l;
! 99: h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
! 100: } else
! 101: {
! 102: if (l > n)
! 103: {
! 104: n = l;
! 105: h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
! 106: }
! 107: }
! 108:
! 109:
! 110: if (len <= HASH_MINBLOCKS)
! 111: {
! 112: for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
! 113: {
! 114: if (IV && (!CMP(c, IV)))
! 115: {
! 116: if ((check_crc(c, buf, len, IV)))
! 117: return (DEATTACK_DETECTED);
! 118: else
! 119: break;
! 120: }
! 121: for (d = buf; d < c; d += SSH_BLOCKSIZE)
! 122: {
! 123: if (!CMP(c, d))
! 124: {
! 125: if ((check_crc(c, buf, len, IV)))
! 126: return (DEATTACK_DETECTED);
! 127: else
! 128: break;
! 129: }
! 130: }
! 131: }
! 132: return (DEATTACK_OK);
! 133: }
! 134: memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
! 135:
! 136: if (IV)
! 137: h[HASH(IV) & (n - 1)] = HASH_IV;
! 138:
! 139:
! 140: for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++)
! 141: {
! 142: for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
! 143: i = (i + 1) & (n - 1))
! 144: {
! 145: if (h[i] == HASH_IV)
! 146: {
! 147: if (!CMP(c, IV))
! 148: {
! 149: if (check_crc(c, buf, len, IV))
! 150: return (DEATTACK_DETECTED);
! 151: else
! 152: break;
! 153: }
! 154: } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE))
! 155: {
! 156: if (check_crc(c, buf, len, IV))
! 157: return (DEATTACK_DETECTED);
! 158: else
! 159: break;
! 160: }
! 161: }
! 162: h[i] = j;
! 163: }
! 164:
! 165: return (DEATTACK_OK);
! 166: }