~ubuntu-branches/ubuntu/utopic/dropbear/utopic-proposed

« back to all changes in this revision

Viewing changes to libtomcrypt/md4.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Johnston
  • Date: 2005-12-08 19:20:21 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208192021-nyp9rwnt77nsg6ty
Tags: 0.47-1
* New upstream release.
* SECURITY: Fix incorrect buffer sizing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2
 
 *
3
 
 * LibTomCrypt is a library that provides various cryptographic
4
 
 * algorithms in a highly modular and flexible manner.
5
 
 *
6
 
 * The library is free for all purposes without any express
7
 
 * guarantee it works.
8
 
 *
9
 
 * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
10
 
 */
11
 
/* Submitted by Dobes Vandermeer  (dobes@smartt.com) */
12
 
#include "mycrypt.h"
13
 
 
14
 
#ifdef MD4
15
 
 
16
 
const struct _hash_descriptor md4_desc =
17
 
{
18
 
    "md4",
19
 
    6,
20
 
    16,
21
 
    64,
22
 
 
23
 
    /* DER encoding (not yet supported) */
24
 
    { 0x00 },
25
 
    0,    
26
 
 
27
 
    &md4_init,
28
 
    &md4_process,
29
 
    &md4_done,
30
 
    &md4_test
31
 
};
32
 
 
33
 
#define S11 3
34
 
#define S12 7
35
 
#define S13 11
36
 
#define S14 19
37
 
#define S21 3
38
 
#define S22 5
39
 
#define S23 9
40
 
#define S24 13
41
 
#define S31 3
42
 
#define S32 9
43
 
#define S33 11
44
 
#define S34 15
45
 
 
46
 
/* F, G and H are basic MD4 functions. */
47
 
#define F(x, y, z) (z ^ (x & (y ^ z)))
48
 
#define G(x, y, z) ((x & y) | (z & (x | y)))
49
 
#define H(x, y, z) ((x) ^ (y) ^ (z))
50
 
 
51
 
/* ROTATE_LEFT rotates x left n bits. */
52
 
#define ROTATE_LEFT(x, n) ROL(x, n)
53
 
 
54
 
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 
55
 
/* Rotation is separate from addition to prevent recomputation */ 
56
 
 
57
 
#define FF(a, b, c, d, x, s) { \
58
 
    (a) += F ((b), (c), (d)) + (x); \
59
 
    (a) = ROTATE_LEFT ((a), (s)); \
60
 
  }
61
 
#define GG(a, b, c, d, x, s) { \
62
 
    (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \
63
 
    (a) = ROTATE_LEFT ((a), (s)); \
64
 
  }
65
 
#define HH(a, b, c, d, x, s) { \
66
 
    (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \
67
 
    (a) = ROTATE_LEFT ((a), (s)); \
68
 
  }
69
 
 
70
 
#ifdef CLEAN_STACK
71
 
static int _md4_compress(hash_state *md, unsigned char *buf)
72
 
#else
73
 
static int  md4_compress(hash_state *md, unsigned char *buf)
74
 
#endif
75
 
{
76
 
    ulong32 x[16], a, b, c, d;
77
 
    int i;
78
 
 
79
 
    /* copy state */
80
 
    a = md->md4.state[0];
81
 
    b = md->md4.state[1];
82
 
    c = md->md4.state[2];
83
 
    d = md->md4.state[3];
84
 
 
85
 
    /* copy the state into 512-bits into W[0..15] */
86
 
    for (i = 0; i < 16; i++) {
87
 
        LOAD32L(x[i], buf + (4*i));
88
 
    }
89
 
 
90
 
    /* Round 1 */ 
91
 
    FF (a, b, c, d, x[ 0], S11); /* 1 */ 
92
 
    FF (d, a, b, c, x[ 1], S12); /* 2 */ 
93
 
    FF (c, d, a, b, x[ 2], S13); /* 3 */ 
94
 
    FF (b, c, d, a, x[ 3], S14); /* 4 */ 
95
 
    FF (a, b, c, d, x[ 4], S11); /* 5 */ 
96
 
    FF (d, a, b, c, x[ 5], S12); /* 6 */ 
97
 
    FF (c, d, a, b, x[ 6], S13); /* 7 */ 
98
 
    FF (b, c, d, a, x[ 7], S14); /* 8 */ 
99
 
    FF (a, b, c, d, x[ 8], S11); /* 9 */ 
100
 
    FF (d, a, b, c, x[ 9], S12); /* 10 */
101
 
    FF (c, d, a, b, x[10], S13); /* 11 */ 
102
 
    FF (b, c, d, a, x[11], S14); /* 12 */
103
 
    FF (a, b, c, d, x[12], S11); /* 13 */
104
 
    FF (d, a, b, c, x[13], S12); /* 14 */ 
105
 
    FF (c, d, a, b, x[14], S13); /* 15 */ 
106
 
    FF (b, c, d, a, x[15], S14); /* 16 */ 
107
 
    
108
 
    /* Round 2 */ 
109
 
    GG (a, b, c, d, x[ 0], S21); /* 17 */ 
110
 
    GG (d, a, b, c, x[ 4], S22); /* 18 */ 
111
 
    GG (c, d, a, b, x[ 8], S23); /* 19 */ 
112
 
    GG (b, c, d, a, x[12], S24); /* 20 */ 
113
 
    GG (a, b, c, d, x[ 1], S21); /* 21 */ 
114
 
    GG (d, a, b, c, x[ 5], S22); /* 22 */ 
115
 
    GG (c, d, a, b, x[ 9], S23); /* 23 */ 
116
 
    GG (b, c, d, a, x[13], S24); /* 24 */ 
117
 
    GG (a, b, c, d, x[ 2], S21); /* 25 */ 
118
 
    GG (d, a, b, c, x[ 6], S22); /* 26 */ 
119
 
    GG (c, d, a, b, x[10], S23); /* 27 */ 
120
 
    GG (b, c, d, a, x[14], S24); /* 28 */ 
121
 
    GG (a, b, c, d, x[ 3], S21); /* 29 */ 
122
 
    GG (d, a, b, c, x[ 7], S22); /* 30 */ 
123
 
    GG (c, d, a, b, x[11], S23); /* 31 */ 
124
 
    GG (b, c, d, a, x[15], S24); /* 32 */ 
125
 
    
126
 
    /* Round 3 */
127
 
    HH (a, b, c, d, x[ 0], S31); /* 33 */ 
128
 
    HH (d, a, b, c, x[ 8], S32); /* 34 */ 
129
 
    HH (c, d, a, b, x[ 4], S33); /* 35 */ 
130
 
    HH (b, c, d, a, x[12], S34); /* 36 */ 
131
 
    HH (a, b, c, d, x[ 2], S31); /* 37 */ 
132
 
    HH (d, a, b, c, x[10], S32); /* 38 */ 
133
 
    HH (c, d, a, b, x[ 6], S33); /* 39 */ 
134
 
    HH (b, c, d, a, x[14], S34); /* 40 */ 
135
 
    HH (a, b, c, d, x[ 1], S31); /* 41 */ 
136
 
    HH (d, a, b, c, x[ 9], S32); /* 42 */ 
137
 
    HH (c, d, a, b, x[ 5], S33); /* 43 */ 
138
 
    HH (b, c, d, a, x[13], S34); /* 44 */ 
139
 
    HH (a, b, c, d, x[ 3], S31); /* 45 */ 
140
 
    HH (d, a, b, c, x[11], S32); /* 46 */ 
141
 
    HH (c, d, a, b, x[ 7], S33); /* 47 */ 
142
 
    HH (b, c, d, a, x[15], S34); /* 48 */ 
143
 
    
144
 
 
145
 
    /* Update our state */
146
 
    md->md4.state[0] = md->md4.state[0] + a;
147
 
    md->md4.state[1] = md->md4.state[1] + b;
148
 
    md->md4.state[2] = md->md4.state[2] + c;
149
 
    md->md4.state[3] = md->md4.state[3] + d;
150
 
 
151
 
    return CRYPT_OK;
152
 
}
153
 
 
154
 
#ifdef CLEAN_STACK
155
 
static int md4_compress(hash_state *md, unsigned char *buf)
156
 
{
157
 
   int err;
158
 
   err = _md4_compress(md, buf);
159
 
   burn_stack(sizeof(ulong32) * 20 + sizeof(int));
160
 
   return err;
161
 
}
162
 
#endif
163
 
 
164
 
int md4_init(hash_state * md)
165
 
{
166
 
   _ARGCHK(md != NULL);
167
 
   md->md4.state[0] = 0x67452301UL;
168
 
   md->md4.state[1] = 0xefcdab89UL;
169
 
   md->md4.state[2] = 0x98badcfeUL;
170
 
   md->md4.state[3] = 0x10325476UL;
171
 
   md->md4.length  = 0;
172
 
   md->md4.curlen  = 0;
173
 
   return CRYPT_OK;
174
 
}
175
 
 
176
 
HASH_PROCESS(md4_process, md4_compress, md4, 64)
177
 
 
178
 
int md4_done(hash_state * md, unsigned char *hash)
179
 
{
180
 
    int i;
181
 
 
182
 
    _ARGCHK(md != NULL);
183
 
    _ARGCHK(hash != NULL);
184
 
 
185
 
    if (md->md4.curlen >= sizeof(md->md4.buf)) {
186
 
       return CRYPT_INVALID_ARG;
187
 
    }
188
 
 
189
 
    /* increase the length of the message */
190
 
    md->md4.length += md->md4.curlen * 8;
191
 
 
192
 
    /* append the '1' bit */
193
 
    md->md4.buf[md->md4.curlen++] = (unsigned char)0x80;
194
 
 
195
 
    /* if the length is currently above 56 bytes we append zeros
196
 
     * then compress.  Then we can fall back to padding zeros and length
197
 
     * encoding like normal.
198
 
     */
199
 
    if (md->md4.curlen > 56) {
200
 
        while (md->md4.curlen < 64) {
201
 
            md->md4.buf[md->md4.curlen++] = (unsigned char)0;
202
 
        }
203
 
        md4_compress(md, md->md4.buf);
204
 
        md->md4.curlen = 0;
205
 
    }
206
 
 
207
 
    /* pad upto 56 bytes of zeroes */
208
 
    while (md->md4.curlen < 56) {
209
 
        md->md4.buf[md->md4.curlen++] = (unsigned char)0;
210
 
    }
211
 
 
212
 
    /* store length */
213
 
    STORE64L(md->md4.length, md->md4.buf+56);
214
 
    md4_compress(md, md->md4.buf);
215
 
 
216
 
    /* copy output */
217
 
    for (i = 0; i < 4; i++) {
218
 
        STORE32L(md->md4.state[i], hash+(4*i));
219
 
    }
220
 
#ifdef CLEAN_STACK
221
 
    zeromem(md, sizeof(hash_state));
222
 
#endif 
223
 
    return CRYPT_OK;
224
 
}
225
 
 
226
 
int md4_test(void)
227
 
{
228
 
 #ifndef LTC_TEST
229
 
    return CRYPT_NOP;
230
 
 #else    
231
 
    static const struct md4_test_case {
232
 
        char *input;
233
 
        unsigned char digest[16];
234
 
    } cases[] = {
235
 
        { "", 
236
 
          {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
237
 
           0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
238
 
        { "a",
239
 
          {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
240
 
           0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
241
 
        { "abc",
242
 
          {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 
243
 
           0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
244
 
        { "message digest", 
245
 
          {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 
246
 
           0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
247
 
        { "abcdefghijklmnopqrstuvwxyz", 
248
 
          {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 
249
 
           0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
250
 
        { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 
251
 
          {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 
252
 
           0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
253
 
        { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 
254
 
          {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 
255
 
           0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
256
 
    };
257
 
    int i;
258
 
    hash_state md;
259
 
    unsigned char digest[16];
260
 
 
261
 
    for(i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
262
 
        md4_init(&md);
263
 
        md4_process(&md, (unsigned char *)cases[i].input, (unsigned long)strlen(cases[i].input));
264
 
        md4_done(&md, digest);
265
 
        if (memcmp(digest, cases[i].digest, 16) != 0) {
266
 
           return CRYPT_FAIL_TESTVECTOR;
267
 
        }
268
 
 
269
 
    }
270
 
    return CRYPT_OK;
271
 
  #endif
272
 
}
273
 
 
274
 
#endif
275
 
 
276