Annotation of src/usr.bin/ssh/deattack.c, Revision 1.3
1.1 dugsong 1: /*
1.3 ! markus 2: * $Id: deattack.c,v 1.2 1999/10/05 02:35:57 dugsong Exp $
1.2 dugsong 3: * Cryptographic attack detector for ssh - source code
4: *
5: * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
6: *
7: * All rights reserved. Redistribution and use in source and binary
8: * forms, with or without modification, are permitted provided that
9: * this copyright notice is retained.
10: *
11: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12: * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
13: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
14: * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
15: * SOFTWARE.
16: *
17: * Ariel Futoransky <futo@core-sdi.com>
18: * <http://www.core-sdi.com> */
1.1 dugsong 19:
20: #include "includes.h"
21: #include "deattack.h"
22: #include "ssh.h"
1.3 ! markus 23: #include "crc32.h"
1.1 dugsong 24: #include "getput.h"
25: #include "xmalloc.h"
26:
27: /* SSH Constants */
28: #define SSH_MAXBLOCKS (32 * 1024)
29: #define SSH_BLOCKSIZE (8)
30:
31: /* Hashing constants */
32: #define HASH_MINSIZE (8 * 1024)
33: #define HASH_ENTRYSIZE (2)
34: #define HASH_FACTOR(x) ((x)*3/2)
35: #define HASH_UNUSEDCHAR (0xff)
36: #define HASH_UNUSED (0xffff)
37: #define HASH_IV (0xfffe)
38:
39: #define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
40:
41:
42: /* Hash function (Input keys are cipher results) */
43: #define HASH(x) GET_32BIT(x)
44:
45: #define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
46:
47:
48: void
49: crc_update(u_int32_t * a, u_int32_t b)
50: {
51: b ^= *a;
52: *a = crc32((unsigned char *) &b, sizeof(b));
53: }
54:
55: /*
56: check_crc
57: detects if a block is used in a particular pattern
58: */
59:
60: int
61: check_crc(unsigned char *S, unsigned char *buf, u_int32_t len, unsigned char *IV)
62: {
63: u_int32_t crc;
64: unsigned char *c;
65:
66: crc = 0;
67: if (IV && !CMP(S, IV))
68: {
69: crc_update(&crc, 1);
70: crc_update(&crc, 0);
71: }
72: for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
73: {
74: if (!CMP(S, c))
75: {
76: crc_update(&crc, 1);
77: crc_update(&crc, 0);
78: } else
79: {
80: crc_update(&crc, 0);
81: crc_update(&crc, 0);
82: }
83: }
84:
85: return (crc == 0);
86: }
87:
88:
89: /*
90: detect_attack
91: Detects a crc32 compensation attack on a packet
92: */
93: int
94: detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
95: {
96: static u_int16_t *h = (u_int16_t *) NULL;
97: static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
98: register u_int32_t i, j;
99: u_int32_t l;
100: register unsigned char *c;
101: unsigned char *d;
102:
103:
104: assert(len <= (SSH_MAXBLOCKS * SSH_BLOCKSIZE));
105: assert(len % SSH_BLOCKSIZE == 0);
106:
107: for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2);
108:
109: if (h == NULL)
110: {
111: debug("Installing crc compensation attack detector.");
112: n = l;
113: h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
114: } else
115: {
116: if (l > n)
117: {
118: n = l;
119: h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
120: }
121: }
122:
123:
124: if (len <= HASH_MINBLOCKS)
125: {
126: for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
127: {
128: if (IV && (!CMP(c, IV)))
129: {
130: if ((check_crc(c, buf, len, IV)))
131: return (DEATTACK_DETECTED);
132: else
133: break;
134: }
135: for (d = buf; d < c; d += SSH_BLOCKSIZE)
136: {
137: if (!CMP(c, d))
138: {
139: if ((check_crc(c, buf, len, IV)))
140: return (DEATTACK_DETECTED);
141: else
142: break;
143: }
144: }
145: }
146: return (DEATTACK_OK);
147: }
148: memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
149:
150: if (IV)
151: h[HASH(IV) & (n - 1)] = HASH_IV;
152:
153:
154: for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++)
155: {
156: for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
157: i = (i + 1) & (n - 1))
158: {
159: if (h[i] == HASH_IV)
160: {
161: if (!CMP(c, IV))
162: {
163: if (check_crc(c, buf, len, IV))
164: return (DEATTACK_DETECTED);
165: else
166: break;
167: }
168: } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE))
169: {
170: if (check_crc(c, buf, len, IV))
171: return (DEATTACK_DETECTED);
172: else
173: break;
174: }
175: }
176: h[i] = j;
177: }
178:
179: return (DEATTACK_OK);
180: }