Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 173 lines (151 sloc) 4.665 kb
fcd53e1 Zsolt Sz. Sztupák putty import
authored
1 /* $OpenBSD: deattack.c,v 1.14 2001/06/23 15:12:18 itojun Exp $ */
2
3 /*
4 * Cryptographic attack detector for ssh - source code
5 *
6 * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
7 *
8 * All rights reserved. Redistribution and use in source and binary
9 * forms, with or without modification, are permitted provided that
10 * this copyright notice is retained.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
14 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
15 * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
16 * SOFTWARE.
17 *
18 * Ariel Futoransky <futo@core-sdi.com>
19 * <http://www.core-sdi.com>
20 *
21 * Modified for use in PuTTY by Simon Tatham
22 */
23
24 #include <assert.h>
25 #include "misc.h"
26 #include "ssh.h"
27
28 typedef unsigned char uchar;
29 typedef unsigned short uint16;
30
31 /* SSH Constants */
32 #define SSH_MAXBLOCKS (32 * 1024)
33 #define SSH_BLOCKSIZE (8)
34
35 /* Hashing constants */
36 #define HASH_MINSIZE (8 * 1024)
37 #define HASH_ENTRYSIZE (sizeof(uint16))
38 #define HASH_FACTOR(x) ((x)*3/2)
39 #define HASH_UNUSEDCHAR (0xff)
40 #define HASH_UNUSED (0xffff)
41 #define HASH_IV (0xfffe)
42
43 #define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
44
45 /* Hash function (Input keys are cipher results) */
46 #define HASH(x) GET_32BIT_MSB_FIRST(x)
47
48 #define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
49
50 uchar ONE[4] = { 1, 0, 0, 0 };
51 uchar ZERO[4] = { 0, 0, 0, 0 };
52
53 struct crcda_ctx {
54 uint16 *h;
55 uint32 n;
56 };
57
58 void *crcda_make_context(void)
59 {
60 struct crcda_ctx *ret = snew(struct crcda_ctx);
61 ret->h = NULL;
62 ret->n = HASH_MINSIZE / HASH_ENTRYSIZE;
63 return ret;
64 }
65
66 void crcda_free_context(void *handle)
67 {
68 struct crcda_ctx *ctx = (struct crcda_ctx *)handle;
69 if (ctx) {
70 sfree(ctx->h);
71 ctx->h = NULL;
72 sfree(ctx);
73 }
74 }
75
76 static void crc_update(uint32 *a, void *b)
77 {
78 *a = crc32_update(*a, b, 4);
79 }
80
81 /* detect if a block is used in a particular pattern */
82 static int check_crc(uchar *S, uchar *buf, uint32 len, uchar *IV)
83 {
84 uint32 crc;
85 uchar *c;
86
87 crc = 0;
88 if (IV && !CMP(S, IV)) {
89 crc_update(&crc, ONE);
90 crc_update(&crc, ZERO);
91 }
92 for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
93 if (!CMP(S, c)) {
94 crc_update(&crc, ONE);
95 crc_update(&crc, ZERO);
96 } else {
97 crc_update(&crc, ZERO);
98 crc_update(&crc, ZERO);
99 }
100 }
101 return (crc == 0);
102 }
103
104 /* Detect a crc32 compensation attack on a packet */
105 int detect_attack(void *handle, uchar *buf, uint32 len, uchar *IV)
106 {
107 struct crcda_ctx *ctx = (struct crcda_ctx *)handle;
108 register uint32 i, j;
109 uint32 l;
110 register uchar *c;
111 uchar *d;
112
113 assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
114 len % SSH_BLOCKSIZE != 0));
115 for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
116 ;
117
118 if (ctx->h == NULL) {
119 ctx->n = l;
120 ctx->h = snewn(ctx->n, uint16);
121 } else {
122 if (l > ctx->n) {
123 ctx->n = l;
124 ctx->h = sresize(ctx->h, ctx->n, uint16);
125 }
126 }
127
128 if (len <= HASH_MINBLOCKS) {
129 for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
130 if (IV && (!CMP(c, IV))) {
131 if ((check_crc(c, buf, len, IV)))
132 return 1; /* attack detected */
133 else
134 break;
135 }
136 for (d = buf; d < c; d += SSH_BLOCKSIZE) {
137 if (!CMP(c, d)) {
138 if ((check_crc(c, buf, len, IV)))
139 return 1; /* attack detected */
140 else
141 break;
142 }
143 }
144 }
145 return 0; /* ok */
146 }
147 memset(ctx->h, HASH_UNUSEDCHAR, ctx->n * HASH_ENTRYSIZE);
148
149 if (IV)
150 ctx->h[HASH(IV) & (ctx->n - 1)] = HASH_IV;
151
152 for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
153 for (i = HASH(c) & (ctx->n - 1); ctx->h[i] != HASH_UNUSED;
154 i = (i + 1) & (ctx->n - 1)) {
155 if (ctx->h[i] == HASH_IV) {
156 if (!CMP(c, IV)) {
157 if (check_crc(c, buf, len, IV))
158 return 1; /* attack detected */
159 else
160 break;
161 }
162 } else if (!CMP(c, buf + ctx->h[i] * SSH_BLOCKSIZE)) {
163 if (check_crc(c, buf, len, IV))
164 return 1; /* attack detected */
165 else
166 break;
167 }
168 }
169 ctx->h[i] = j;
170 }
171 return 0; /* ok */
172 }
Something went wrong with that request. Please try again.