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

Revision 12648, 3.1 KB checked in by danw, 26 years ago (diff)
merge changes
Line 
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
34void
35crc_update(word32 * a, word32 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
46int
47check_crc(unsigned char *S, unsigned char *buf, word32 len, unsigned char *IV)
48{
49  word32          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 */
79int
80detect_attack(unsigned char *buf, word32 len, unsigned char *IV)
81{
82  static word16  *h = (word16 *) NULL;
83  static word16   n = HASH_MINSIZE / HASH_ENTRYSIZE;
84  register word32 i, j;
85  word32          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 = (word16 *) xmalloc(n * HASH_ENTRYSIZE);
100  } else
101  {
102    if (l > n)
103    {
104      n = l;
105      h = (word16 *) 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}
Note: See TracBrowser for help on using the repository browser.