source: zzuf/trunk/src/md5.c @ 1761

Last change on this file since 1761 was 1761, checked in by sam, 7 years ago
  • Cleaned up md5.c.
  • Do not convert words to little endian if the architecture is already little endian.
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  md5.c: MD5 computation. Written and put into the public domain
17 *  by Colin Plumb in 1993.
18 */
19
20#include "config.h"
21
22#if defined HAVE_STDINT_H
23#   include <stdint.h>
24#elif defined HAVE_INTTYPES_H
25#   include <inttypes.h>
26#endif
27#if defined HAVE_ENDIAN_H
28#   include <endian.h>
29#endif
30#include <string.h>
31#include <stdlib.h>
32
33#include "md5.h"
34
35struct md5
36{
37    uint32_t buf[4];
38    uint32_t bits[2];
39    uint32_t in[64];
40};
41
42static void swapwords(uint32_t *buf, unsigned words);
43static void transform(uint32_t buf[4], uint32_t in[16]);
44
45struct md5 *_zz_md5_init(void)
46{
47    struct md5 *ctx = malloc(sizeof(struct md5));
48
49    ctx->buf[0] = 0x67452301;
50    ctx->buf[1] = 0xefcdab89;
51    ctx->buf[2] = 0x98badcfe;
52    ctx->buf[3] = 0x10325476;
53
54    ctx->bits[0] = 0;
55    ctx->bits[1] = 0;
56
57    return ctx;
58}
59
60void _zz_md5_add(struct md5 *ctx, uint8_t *buf, unsigned len)
61{
62    uint32_t t;
63
64    t = ctx->bits[0];
65    if((ctx->bits[0] = t + ((uint32_t)len << 3)) < t)
66        ctx->bits[1]++;
67    ctx->bits[1] += len >> 29;
68
69    t = (t >> 3) & 0x3f;
70
71    if(t)
72    {
73        uint8_t *p = (uint8_t *)ctx->in + t;
74
75        t = 64 - t;
76        if(len < t)
77        {
78            memcpy(p, buf, len);
79            return;
80        }
81        memcpy(p, buf, t);
82        swapwords(ctx->in, 64 / 4);
83        transform(ctx->buf, ctx->in);
84        buf += t;
85        len -= t;
86    }
87
88    while(len >= 64)
89    {
90        memcpy(ctx->in, buf, 64);
91        swapwords(ctx->in, 64 / 4);
92        transform(ctx->buf, ctx->in);
93        buf += 64;
94        len -= 64;
95    }
96
97    memcpy(ctx->in, buf, len);
98}
99
100void _zz_md5_fini(uint8_t *digest, struct md5 *ctx)
101{
102    unsigned count;
103    uint8_t *p;
104
105    count = (ctx->bits[0] >> 3) & 0x3F;
106    p = (uint8_t *)ctx->in + count;
107    *p++ = 0x80;
108
109    count = 64 - 1 - count;
110    if(count < 8)
111    {
112        memset(p, 0, count);
113        swapwords(ctx->in, 64 / 4);
114        transform(ctx->buf, ctx->in);
115        memset(ctx->in, 0, 56);
116    }
117    else
118        memset(p, 0, count - 8);
119
120    swapwords(ctx->in, 56 / 4);
121    memcpy(ctx->in + 56 / 4, ctx->bits, 8);
122    transform(ctx->buf, ctx->in);
123    swapwords(ctx->buf, 16 / 4);
124    memcpy(digest, ctx->buf, 16);
125    free(ctx);
126}
127
128static void swapwords(uint32_t *buf, unsigned words)
129{
130    /* XXX: no need to swap words on little endian machines */
131#if defined HAVE_ENDIAN_H
132    if(__BYTE_ORDER == __LITTLE_ENDIAN)
133        return;
134#else
135    /* This is compile-time optimised with at least -O1 or -Os */
136    uint32_t const tmp = 0x12345678;
137    if(*(uint8_t const *)&tmp == 0x78)
138        return;
139#endif
140
141    while(words > 0)
142    {
143        uint8_t *b = (uint8_t *)buf;
144        *buf++ = (uint32_t)((unsigned) b[3] << 8 | b[2]) << 16 |
145                            ((unsigned) b[1] << 8 | b[0]);
146        words--;
147    }
148}
149
150/* #define F1(x, y, z) (x & y | ~x & z) */
151#define F1(x, y, z) (z ^ (x & (y ^ z)))
152#define F2(x, y, z) F1(z, x, y)
153#define F3(x, y, z) (x ^ y ^ z)
154#define F4(x, y, z) (y ^ (x | ~z))
155
156#define MD5STEP(f, w, x, y, z, data, s) \
157    (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
158
159static void transform(uint32_t buf[4], uint32_t in[16])
160{
161    uint32_t a = buf[0];
162    uint32_t b = buf[1];
163    uint32_t c = buf[2];
164    uint32_t d = buf[3];
165
166    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
167    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
168    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
169    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
170    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
171    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
172    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
173    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
174    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
175    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
176    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
177    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
178    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
179    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
180    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
181    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
182
183    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
184    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
185    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
186    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
187    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
188    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
189    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
190    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
191    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
192    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
193    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
194    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
195    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
196    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
197    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
198    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
199
200    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
201    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
202    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
203    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
204    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
205    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
206    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
207    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
208    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
209    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
210    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
211    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
212    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
213    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
214    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
215    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
216
217    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
218    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
219    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
220    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
221    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
222    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
223    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
224    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
225    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
226    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
227    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
228    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
229    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
230    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
231    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
232    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
233
234    buf[0] += a;
235    buf[1] += b;
236    buf[2] += c;
237    buf[3] += d;
238}
239
Note: See TracBrowser for help on using the repository browser.