source: filezilla/trunk/fuentes/src/putty/sshcrcda.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 4.6 KB
Line 
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
28typedef unsigned char uchar;
29typedef 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
50uchar ONE[4] = { 1, 0, 0, 0 };
51uchar ZERO[4] = { 0, 0, 0, 0 };
52
53struct crcda_ctx {
54    uint16 *h;
55    uint32 n;
56};
57
58void *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
66void 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
76static 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 */
82static 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 */
105int 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}
Note: See TracBrowser for help on using the repository browser.