~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/libpq/md5.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      md5.c
 
3
 *
 
4
 *      Implements      the  MD5 Message-Digest Algorithm as specified in
 
5
 *      RFC  1321.      This  implementation  is a simple one, in that it
 
6
 *      needs  every  input  byte  to  be  buffered  before doing any
 
7
 *      calculations.  I  do  not  expect  this  file  to be used for
 
8
 *      general  purpose  MD5'ing  of large amounts of data, only for
 
9
 *      generating hashed passwords from limited input.
 
10
 *
 
11
 *      Sverre H. Huseby <sverrehu@online.no>
 
12
 *
 
13
 *      Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
14
 *      Portions Copyright (c) 1994, Regents of the University of California
 
15
 *
 
16
 * IDENTIFICATION
 
17
 *        $PostgreSQL: pgsql/src/backend/libpq/md5.c,v 1.27 2004-12-31 21:59:50 pgsql Exp $
 
18
 */
 
19
 
 
20
 
 
21
#if ! defined(FRONTEND)
 
22
#include "postgres.h"
 
23
#include "libpq/crypt.h"
 
24
#endif
 
25
 
 
26
#ifdef FRONTEND
 
27
#include "postgres_fe.h"
 
28
#include "libpq/crypt.h"
 
29
 
 
30
#undef palloc
 
31
#define palloc malloc
 
32
#undef pfree
 
33
#define pfree free
 
34
#endif   /* FRONTEND */
 
35
 
 
36
 
 
37
/*
 
38
 *      PRIVATE FUNCTIONS
 
39
 */
 
40
 
 
41
 
 
42
/*
 
43
 *      The returned array is allocated using malloc.  the caller should free it
 
44
 *      when it is no longer needed.
 
45
 */
 
46
static uint8 *
 
47
createPaddedCopyWithLength(uint8 *b, uint32 *l)
 
48
{
 
49
        uint8      *ret;
 
50
        uint32          q;
 
51
        uint32          len,
 
52
                                newLen448;
 
53
        uint32          len_high,
 
54
                                len_low;                /* 64-bit value split into 32-bit sections */
 
55
 
 
56
        len = ((b == NULL) ? 0 : *l);
 
57
        newLen448 = len + 64 - (len % 64) - 8;
 
58
        if (newLen448 <= len)
 
59
                newLen448 += 64;
 
60
 
 
61
        *l = newLen448 + 8;
 
62
        if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL)
 
63
                return NULL;
 
64
 
 
65
        if (b != NULL)
 
66
                memcpy(ret, b, sizeof(uint8) * len);
 
67
 
 
68
        /* pad */
 
69
        ret[len] = 0x80;
 
70
        for (q = len + 1; q < newLen448; q++)
 
71
                ret[q] = 0x00;
 
72
 
 
73
        /* append length as a 64 bit bitcount */
 
74
        len_low = len;
 
75
        /* split into two 32-bit values */
 
76
        /* we only look at the bottom 32-bits */
 
77
        len_high = len >> 29;
 
78
        len_low <<= 3;
 
79
        q = newLen448;
 
80
        ret[q++] = (len_low & 0xff);
 
81
        len_low >>= 8;
 
82
        ret[q++] = (len_low & 0xff);
 
83
        len_low >>= 8;
 
84
        ret[q++] = (len_low & 0xff);
 
85
        len_low >>= 8;
 
86
        ret[q++] = (len_low & 0xff);
 
87
        ret[q++] = (len_high & 0xff);
 
88
        len_high >>= 8;
 
89
        ret[q++] = (len_high & 0xff);
 
90
        len_high >>= 8;
 
91
        ret[q++] = (len_high & 0xff);
 
92
        len_high >>= 8;
 
93
        ret[q] = (len_high & 0xff);
 
94
 
 
95
        return ret;
 
96
}
 
97
 
 
98
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
 
99
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
 
100
#define H(x, y, z) ((x) ^ (y) ^ (z))
 
101
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
 
102
#define ROT_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 
103
 
 
104
static void
 
105
doTheRounds(uint32 X[16], uint32 state[4])
 
106
{
 
107
        uint32          a,
 
108
                                b,
 
109
                                c,
 
110
                                d;
 
111
 
 
112
        a = state[0];
 
113
        b = state[1];
 
114
        c = state[2];
 
115
        d = state[3];
 
116
 
 
117
        /* round 1 */
 
118
        a = b + ROT_LEFT((a + F(b, c, d) + X[0] + 0xd76aa478), 7);      /* 1 */
 
119
        d = a + ROT_LEFT((d + F(a, b, c) + X[1] + 0xe8c7b756), 12); /* 2 */
 
120
        c = d + ROT_LEFT((c + F(d, a, b) + X[2] + 0x242070db), 17); /* 3 */
 
121
        b = c + ROT_LEFT((b + F(c, d, a) + X[3] + 0xc1bdceee), 22); /* 4 */
 
122
        a = b + ROT_LEFT((a + F(b, c, d) + X[4] + 0xf57c0faf), 7);      /* 5 */
 
123
        d = a + ROT_LEFT((d + F(a, b, c) + X[5] + 0x4787c62a), 12); /* 6 */
 
124
        c = d + ROT_LEFT((c + F(d, a, b) + X[6] + 0xa8304613), 17); /* 7 */
 
125
        b = c + ROT_LEFT((b + F(c, d, a) + X[7] + 0xfd469501), 22); /* 8 */
 
126
        a = b + ROT_LEFT((a + F(b, c, d) + X[8] + 0x698098d8), 7);      /* 9 */
 
127
        d = a + ROT_LEFT((d + F(a, b, c) + X[9] + 0x8b44f7af), 12); /* 10 */
 
128
        c = d + ROT_LEFT((c + F(d, a, b) + X[10] + 0xffff5bb1), 17);            /* 11 */
 
129
        b = c + ROT_LEFT((b + F(c, d, a) + X[11] + 0x895cd7be), 22);            /* 12 */
 
130
        a = b + ROT_LEFT((a + F(b, c, d) + X[12] + 0x6b901122), 7); /* 13 */
 
131
        d = a + ROT_LEFT((d + F(a, b, c) + X[13] + 0xfd987193), 12);            /* 14 */
 
132
        c = d + ROT_LEFT((c + F(d, a, b) + X[14] + 0xa679438e), 17);            /* 15 */
 
133
        b = c + ROT_LEFT((b + F(c, d, a) + X[15] + 0x49b40821), 22);            /* 16 */
 
134
 
 
135
        /* round 2 */
 
136
        a = b + ROT_LEFT((a + G(b, c, d) + X[1] + 0xf61e2562), 5);      /* 17 */
 
137
        d = a + ROT_LEFT((d + G(a, b, c) + X[6] + 0xc040b340), 9);      /* 18 */
 
138
        c = d + ROT_LEFT((c + G(d, a, b) + X[11] + 0x265e5a51), 14);            /* 19 */
 
139
        b = c + ROT_LEFT((b + G(c, d, a) + X[0] + 0xe9b6c7aa), 20); /* 20 */
 
140
        a = b + ROT_LEFT((a + G(b, c, d) + X[5] + 0xd62f105d), 5);      /* 21 */
 
141
        d = a + ROT_LEFT((d + G(a, b, c) + X[10] + 0x02441453), 9); /* 22 */
 
142
        c = d + ROT_LEFT((c + G(d, a, b) + X[15] + 0xd8a1e681), 14);            /* 23 */
 
143
        b = c + ROT_LEFT((b + G(c, d, a) + X[4] + 0xe7d3fbc8), 20); /* 24 */
 
144
        a = b + ROT_LEFT((a + G(b, c, d) + X[9] + 0x21e1cde6), 5);      /* 25 */
 
145
        d = a + ROT_LEFT((d + G(a, b, c) + X[14] + 0xc33707d6), 9); /* 26 */
 
146
        c = d + ROT_LEFT((c + G(d, a, b) + X[3] + 0xf4d50d87), 14); /* 27 */
 
147
        b = c + ROT_LEFT((b + G(c, d, a) + X[8] + 0x455a14ed), 20); /* 28 */
 
148
        a = b + ROT_LEFT((a + G(b, c, d) + X[13] + 0xa9e3e905), 5); /* 29 */
 
149
        d = a + ROT_LEFT((d + G(a, b, c) + X[2] + 0xfcefa3f8), 9);      /* 30 */
 
150
        c = d + ROT_LEFT((c + G(d, a, b) + X[7] + 0x676f02d9), 14); /* 31 */
 
151
        b = c + ROT_LEFT((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20);            /* 32 */
 
152
 
 
153
        /* round 3 */
 
154
        a = b + ROT_LEFT((a + H(b, c, d) + X[5] + 0xfffa3942), 4);      /* 33 */
 
155
        d = a + ROT_LEFT((d + H(a, b, c) + X[8] + 0x8771f681), 11); /* 34 */
 
156
        c = d + ROT_LEFT((c + H(d, a, b) + X[11] + 0x6d9d6122), 16);            /* 35 */
 
157
        b = c + ROT_LEFT((b + H(c, d, a) + X[14] + 0xfde5380c), 23);            /* 36 */
 
158
        a = b + ROT_LEFT((a + H(b, c, d) + X[1] + 0xa4beea44), 4);      /* 37 */
 
159
        d = a + ROT_LEFT((d + H(a, b, c) + X[4] + 0x4bdecfa9), 11); /* 38 */
 
160
        c = d + ROT_LEFT((c + H(d, a, b) + X[7] + 0xf6bb4b60), 16); /* 39 */
 
161
        b = c + ROT_LEFT((b + H(c, d, a) + X[10] + 0xbebfbc70), 23);            /* 40 */
 
162
        a = b + ROT_LEFT((a + H(b, c, d) + X[13] + 0x289b7ec6), 4); /* 41 */
 
163
        d = a + ROT_LEFT((d + H(a, b, c) + X[0] + 0xeaa127fa), 11); /* 42 */
 
164
        c = d + ROT_LEFT((c + H(d, a, b) + X[3] + 0xd4ef3085), 16); /* 43 */
 
165
        b = c + ROT_LEFT((b + H(c, d, a) + X[6] + 0x04881d05), 23); /* 44 */
 
166
        a = b + ROT_LEFT((a + H(b, c, d) + X[9] + 0xd9d4d039), 4);      /* 45 */
 
167
        d = a + ROT_LEFT((d + H(a, b, c) + X[12] + 0xe6db99e5), 11);            /* 46 */
 
168
        c = d + ROT_LEFT((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16);            /* 47 */
 
169
        b = c + ROT_LEFT((b + H(c, d, a) + X[2] + 0xc4ac5665), 23); /* 48 */
 
170
 
 
171
        /* round 4 */
 
172
        a = b + ROT_LEFT((a + I(b, c, d) + X[0] + 0xf4292244), 6);      /* 49 */
 
173
        d = a + ROT_LEFT((d + I(a, b, c) + X[7] + 0x432aff97), 10); /* 50 */
 
174
        c = d + ROT_LEFT((c + I(d, a, b) + X[14] + 0xab9423a7), 15);            /* 51 */
 
175
        b = c + ROT_LEFT((b + I(c, d, a) + X[5] + 0xfc93a039), 21); /* 52 */
 
176
        a = b + ROT_LEFT((a + I(b, c, d) + X[12] + 0x655b59c3), 6); /* 53 */
 
177
        d = a + ROT_LEFT((d + I(a, b, c) + X[3] + 0x8f0ccc92), 10); /* 54 */
 
178
        c = d + ROT_LEFT((c + I(d, a, b) + X[10] + 0xffeff47d), 15);            /* 55 */
 
179
        b = c + ROT_LEFT((b + I(c, d, a) + X[1] + 0x85845dd1), 21); /* 56 */
 
180
        a = b + ROT_LEFT((a + I(b, c, d) + X[8] + 0x6fa87e4f), 6);      /* 57 */
 
181
        d = a + ROT_LEFT((d + I(a, b, c) + X[15] + 0xfe2ce6e0), 10);            /* 58 */
 
182
        c = d + ROT_LEFT((c + I(d, a, b) + X[6] + 0xa3014314), 15); /* 59 */
 
183
        b = c + ROT_LEFT((b + I(c, d, a) + X[13] + 0x4e0811a1), 21);            /* 60 */
 
184
        a = b + ROT_LEFT((a + I(b, c, d) + X[4] + 0xf7537e82), 6);      /* 61 */
 
185
        d = a + ROT_LEFT((d + I(a, b, c) + X[11] + 0xbd3af235), 10);            /* 62 */
 
186
        c = d + ROT_LEFT((c + I(d, a, b) + X[2] + 0x2ad7d2bb), 15); /* 63 */
 
187
        b = c + ROT_LEFT((b + I(c, d, a) + X[9] + 0xeb86d391), 21); /* 64 */
 
188
 
 
189
        state[0] += a;
 
190
        state[1] += b;
 
191
        state[2] += c;
 
192
        state[3] += d;
 
193
}
 
194
 
 
195
static int
 
196
calculateDigestFromBuffer(uint8 *b, uint32 len, uint8 sum[16])
 
197
{
 
198
        register uint32 i,
 
199
                                j,
 
200
                                k,
 
201
                                newI;
 
202
        uint32          l;
 
203
        uint8      *input;
 
204
        register uint32 *wbp;
 
205
        uint32          workBuff[16],
 
206
                                state[4];
 
207
 
 
208
        l = len;
 
209
 
 
210
        state[0] = 0x67452301;
 
211
        state[1] = 0xEFCDAB89;
 
212
        state[2] = 0x98BADCFE;
 
213
        state[3] = 0x10325476;
 
214
 
 
215
        if ((input = createPaddedCopyWithLength(b, &l)) == NULL)
 
216
                return 0;
 
217
 
 
218
        for (i = 0;;)
 
219
        {
 
220
                if ((newI = i + 16 * 4) > l)
 
221
                        break;
 
222
                k = i + 3;
 
223
                for (j = 0; j < 16; j++)
 
224
                {
 
225
                        wbp = (workBuff + j);
 
226
                        *wbp = input[k--];
 
227
                        *wbp <<= 8;
 
228
                        *wbp |= input[k--];
 
229
                        *wbp <<= 8;
 
230
                        *wbp |= input[k--];
 
231
                        *wbp <<= 8;
 
232
                        *wbp |= input[k];
 
233
                        k += 7;
 
234
                }
 
235
                doTheRounds(workBuff, state);
 
236
                i = newI;
 
237
        }
 
238
        free(input);
 
239
 
 
240
        j = 0;
 
241
        for (i = 0; i < 4; i++)
 
242
        {
 
243
                k = state[i];
 
244
                sum[j++] = (k & 0xff);
 
245
                k >>= 8;
 
246
                sum[j++] = (k & 0xff);
 
247
                k >>= 8;
 
248
                sum[j++] = (k & 0xff);
 
249
                k >>= 8;
 
250
                sum[j++] = (k & 0xff);
 
251
        }
 
252
        return 1;
 
253
}
 
254
 
 
255
static void
 
256
bytesToHex(uint8 b[16], char *s)
 
257
{
 
258
        static const char *hex = "0123456789abcdef";
 
259
        int                     q,
 
260
                                w;
 
261
 
 
262
        for (q = 0, w = 0; q < 16; q++)
 
263
        {
 
264
                s[w++] = hex[(b[q] >> 4) & 0x0F];
 
265
                s[w++] = hex[b[q] & 0x0F];
 
266
        }
 
267
        s[w] = '\0';
 
268
}
 
269
 
 
270
/*
 
271
 *      PUBLIC FUNCTIONS
 
272
 */
 
273
 
 
274
/*
 
275
 *      md5_hash
 
276
 *
 
277
 *      Calculates the MD5 sum of the bytes in a buffer.
 
278
 *
 
279
 *      SYNOPSIS          #include "crypt.h"
 
280
 *                                int md5_hash(const void *buff, size_t len, char *hexsum)
 
281
 *
 
282
 *      INPUT             buff    the buffer containing the bytes that you want
 
283
 *                                                the MD5 sum of.
 
284
 *                                len     number of bytes in the buffer.
 
285
 *
 
286
 *      OUTPUT            hexsum  the MD5 sum as a '\0'-terminated string of
 
287
 *                                                hexadecimal digits.  an MD5 sum is 16 bytes long.
 
288
 *                                                each byte is represented by two heaxadecimal
 
289
 *                                                characters.  you thus need to provide an array
 
290
 *                                                of 33 characters, including the trailing '\0'.
 
291
 *
 
292
 *      RETURNS           0 on failure (out of memory for internal buffers) or
 
293
 *                                non-zero on success.
 
294
 *
 
295
 *      STANDARDS         MD5 is described in RFC 1321.
 
296
 *
 
297
 *      AUTHOR            Sverre H. Huseby <sverrehu@online.no>
 
298
 *
 
299
 */
 
300
bool
 
301
md5_hash(const void *buff, size_t len, char *hexsum)
 
302
{
 
303
        uint8           sum[16];
 
304
 
 
305
        if (!calculateDigestFromBuffer((uint8 *) buff, len, sum))
 
306
                return false;
 
307
 
 
308
        bytesToHex(sum, hexsum);
 
309
        return true;
 
310
}
 
311
 
 
312
 
 
313
 
 
314
/*
 
315
 * Computes MD5 checksum of "passwd" (a null-terminated string) followed
 
316
 * by "salt" (which need not be null-terminated).
 
317
 *
 
318
 * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
 
319
 * Hence, the output buffer "buf" must be at least 36 bytes long.
 
320
 *
 
321
 * Returns TRUE if okay, FALSE on error (out of memory).
 
322
 */
 
323
bool
 
324
EncryptMD5(const char *passwd, const char *salt, size_t salt_len,
 
325
                   char *buf)
 
326
{
 
327
        size_t          passwd_len = strlen(passwd);
 
328
        char       *crypt_buf = palloc(passwd_len + salt_len);
 
329
        bool            ret;
 
330
 
 
331
        /*
 
332
         * Place salt at the end because it may be known by users trying to
 
333
         * crack the MD5 output.
 
334
         */
 
335
        strcpy(crypt_buf, passwd);
 
336
        memcpy(crypt_buf + passwd_len, salt, salt_len);
 
337
 
 
338
        strcpy(buf, "md5");
 
339
        ret = md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
 
340
 
 
341
        pfree(crypt_buf);
 
342
 
 
343
        return ret;
 
344
}