source: trunk/third/ssh/deattack.c @ 12648

Revision 12648, 3.1 KB checked in by danw, 26 years ago (diff)
merge changes
RevLine 
[11647]1/*
[12648]2 * Id: deattack.c,v 1.9 1998/06/27 00:02:22 futo Exp  Cryptographic attack
[11647]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
[11738]33
34void
35crc_update(word32 * a, word32 b)
36{
37  b ^= *a;
38  *a = crc32((unsigned char *) &b, sizeof(b));
39}
40
[11647]41/*
42   check_crc
43   detects if a block is used in a particular pattern
44 */
[11738]45
[11647]46int
[11738]47check_crc(unsigned char *S, unsigned char *buf, word32 len, unsigned char *IV)
[11647]48{
[11738]49  word32          crc;
50  unsigned char  *c;
[11647]51
[11738]52  crc = 0;
53  if (IV && !CMP(S, IV))
54  {
55    crc_update(&crc, 1);
56    crc_update(&crc, 0);
57  }
[11647]58  for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
[11738]59  {
60    if (!CMP(S, c))
[11647]61    {
[11738]62      crc_update(&crc, 1);
63      crc_update(&crc, 0);
64    } else
[11647]65    {
[11738]66      crc_update(&crc, 0);
67      crc_update(&crc, 0);
[11647]68    }
[11738]69  }
[11647]70
[11738]71  return (crc == 0);
[11647]72}
73
74
75/*
76   detect_attack
77   Detects a crc32 compensation attack on a packet
78 */
79int
[11738]80detect_attack(unsigned char *buf, word32 len, unsigned char *IV)
[11647]81{
[11738]82  static word16  *h = (word16 *) NULL;
83  static word16   n = HASH_MINSIZE / HASH_ENTRYSIZE;
[11647]84  register word32 i, j;
[11738]85  word32          l;
[11647]86  register unsigned char *c;
[11738]87  unsigned char  *d;
[11647]88
89
[11738]90  assert(len <= (SSH_MAXBLOCKS * SSH_BLOCKSIZE));
91  assert(len % SSH_BLOCKSIZE == 0);
[11647]92
[11738]93  for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2);
[11647]94
95  if (h == NULL)
[11738]96  {
97    debug("Installing crc compensation attack detector.");
98    n = l;
99    h = (word16 *) xmalloc(n * HASH_ENTRYSIZE);
100  } else
101  {
102    if (l > n)
[11647]103    {
104      n = l;
[11738]105      h = (word16 *) xrealloc(h, n * HASH_ENTRYSIZE);
[11647]106    }
[11738]107  }
[11647]108
109
110  if (len <= HASH_MINBLOCKS)
[11738]111  {
112    for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
[11647]113    {
[11738]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))
[11647]124        {
[11738]125          if ((check_crc(c, buf, len, IV)))
126            return (DEATTACK_DETECTED);
127          else
128            break;
[11647]129        }
[11738]130      }
[11647]131    }
[11738]132    return (DEATTACK_OK);
133  }
134  memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
[11647]135
136  if (IV)
[11738]137    h[HASH(IV) & (n - 1)] = HASH_IV;
[11647]138
139
140  for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++)
[11738]141  {
142    for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
143         i = (i + 1) & (n - 1))
[11647]144    {
[11738]145      if (h[i] == HASH_IV)
146      {
147        if (!CMP(c, IV))
[11647]148        {
[11738]149          if (check_crc(c, buf, len, IV))
150            return (DEATTACK_DETECTED);
[11647]151          else
[11738]152            break;
[11647]153        }
[11738]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      }
[11647]161    }
[11738]162    h[i] = j;
163  }
[11647]164
165  return (DEATTACK_OK);
166}
Note: See TracBrowser for help on using the repository browser.