00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "c.h"
00022
00023 #include "libpq/md5.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 static uint8 *
00036 createPaddedCopyWithLength(const uint8 *b, uint32 *l)
00037 {
00038 uint8 *ret;
00039 uint32 q;
00040 uint32 len,
00041 newLen448;
00042 uint32 len_high,
00043 len_low;
00044
00045 len = ((b == NULL) ? 0 : *l);
00046 newLen448 = len + 64 - (len % 64) - 8;
00047 if (newLen448 <= len)
00048 newLen448 += 64;
00049
00050 *l = newLen448 + 8;
00051 if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL)
00052 return NULL;
00053
00054 if (b != NULL)
00055 memcpy(ret, b, sizeof(uint8) * len);
00056
00057
00058 ret[len] = 0x80;
00059 for (q = len + 1; q < newLen448; q++)
00060 ret[q] = 0x00;
00061
00062
00063 len_low = len;
00064
00065
00066 len_high = len >> 29;
00067 len_low <<= 3;
00068 q = newLen448;
00069 ret[q++] = (len_low & 0xff);
00070 len_low >>= 8;
00071 ret[q++] = (len_low & 0xff);
00072 len_low >>= 8;
00073 ret[q++] = (len_low & 0xff);
00074 len_low >>= 8;
00075 ret[q++] = (len_low & 0xff);
00076 ret[q++] = (len_high & 0xff);
00077 len_high >>= 8;
00078 ret[q++] = (len_high & 0xff);
00079 len_high >>= 8;
00080 ret[q++] = (len_high & 0xff);
00081 len_high >>= 8;
00082 ret[q] = (len_high & 0xff);
00083
00084 return ret;
00085 }
00086
00087 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00088 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00089 #define H(x, y, z) ((x) ^ (y) ^ (z))
00090 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00091 #define ROT_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00092
00093 static void
00094 doTheRounds(uint32 X[16], uint32 state[4])
00095 {
00096 uint32 a,
00097 b,
00098 c,
00099 d;
00100
00101 a = state[0];
00102 b = state[1];
00103 c = state[2];
00104 d = state[3];
00105
00106
00107 a = b + ROT_LEFT((a + F(b, c, d) + X[0] + 0xd76aa478), 7);
00108 d = a + ROT_LEFT((d + F(a, b, c) + X[1] + 0xe8c7b756), 12);
00109 c = d + ROT_LEFT((c + F(d, a, b) + X[2] + 0x242070db), 17);
00110 b = c + ROT_LEFT((b + F(c, d, a) + X[3] + 0xc1bdceee), 22);
00111 a = b + ROT_LEFT((a + F(b, c, d) + X[4] + 0xf57c0faf), 7);
00112 d = a + ROT_LEFT((d + F(a, b, c) + X[5] + 0x4787c62a), 12);
00113 c = d + ROT_LEFT((c + F(d, a, b) + X[6] + 0xa8304613), 17);
00114 b = c + ROT_LEFT((b + F(c, d, a) + X[7] + 0xfd469501), 22);
00115 a = b + ROT_LEFT((a + F(b, c, d) + X[8] + 0x698098d8), 7);
00116 d = a + ROT_LEFT((d + F(a, b, c) + X[9] + 0x8b44f7af), 12);
00117 c = d + ROT_LEFT((c + F(d, a, b) + X[10] + 0xffff5bb1), 17);
00118 b = c + ROT_LEFT((b + F(c, d, a) + X[11] + 0x895cd7be), 22);
00119 a = b + ROT_LEFT((a + F(b, c, d) + X[12] + 0x6b901122), 7);
00120 d = a + ROT_LEFT((d + F(a, b, c) + X[13] + 0xfd987193), 12);
00121 c = d + ROT_LEFT((c + F(d, a, b) + X[14] + 0xa679438e), 17);
00122 b = c + ROT_LEFT((b + F(c, d, a) + X[15] + 0x49b40821), 22);
00123
00124
00125 a = b + ROT_LEFT((a + G(b, c, d) + X[1] + 0xf61e2562), 5);
00126 d = a + ROT_LEFT((d + G(a, b, c) + X[6] + 0xc040b340), 9);
00127 c = d + ROT_LEFT((c + G(d, a, b) + X[11] + 0x265e5a51), 14);
00128 b = c + ROT_LEFT((b + G(c, d, a) + X[0] + 0xe9b6c7aa), 20);
00129 a = b + ROT_LEFT((a + G(b, c, d) + X[5] + 0xd62f105d), 5);
00130 d = a + ROT_LEFT((d + G(a, b, c) + X[10] + 0x02441453), 9);
00131 c = d + ROT_LEFT((c + G(d, a, b) + X[15] + 0xd8a1e681), 14);
00132 b = c + ROT_LEFT((b + G(c, d, a) + X[4] + 0xe7d3fbc8), 20);
00133 a = b + ROT_LEFT((a + G(b, c, d) + X[9] + 0x21e1cde6), 5);
00134 d = a + ROT_LEFT((d + G(a, b, c) + X[14] + 0xc33707d6), 9);
00135 c = d + ROT_LEFT((c + G(d, a, b) + X[3] + 0xf4d50d87), 14);
00136 b = c + ROT_LEFT((b + G(c, d, a) + X[8] + 0x455a14ed), 20);
00137 a = b + ROT_LEFT((a + G(b, c, d) + X[13] + 0xa9e3e905), 5);
00138 d = a + ROT_LEFT((d + G(a, b, c) + X[2] + 0xfcefa3f8), 9);
00139 c = d + ROT_LEFT((c + G(d, a, b) + X[7] + 0x676f02d9), 14);
00140 b = c + ROT_LEFT((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20);
00141
00142
00143 a = b + ROT_LEFT((a + H(b, c, d) + X[5] + 0xfffa3942), 4);
00144 d = a + ROT_LEFT((d + H(a, b, c) + X[8] + 0x8771f681), 11);
00145 c = d + ROT_LEFT((c + H(d, a, b) + X[11] + 0x6d9d6122), 16);
00146 b = c + ROT_LEFT((b + H(c, d, a) + X[14] + 0xfde5380c), 23);
00147 a = b + ROT_LEFT((a + H(b, c, d) + X[1] + 0xa4beea44), 4);
00148 d = a + ROT_LEFT((d + H(a, b, c) + X[4] + 0x4bdecfa9), 11);
00149 c = d + ROT_LEFT((c + H(d, a, b) + X[7] + 0xf6bb4b60), 16);
00150 b = c + ROT_LEFT((b + H(c, d, a) + X[10] + 0xbebfbc70), 23);
00151 a = b + ROT_LEFT((a + H(b, c, d) + X[13] + 0x289b7ec6), 4);
00152 d = a + ROT_LEFT((d + H(a, b, c) + X[0] + 0xeaa127fa), 11);
00153 c = d + ROT_LEFT((c + H(d, a, b) + X[3] + 0xd4ef3085), 16);
00154 b = c + ROT_LEFT((b + H(c, d, a) + X[6] + 0x04881d05), 23);
00155 a = b + ROT_LEFT((a + H(b, c, d) + X[9] + 0xd9d4d039), 4);
00156 d = a + ROT_LEFT((d + H(a, b, c) + X[12] + 0xe6db99e5), 11);
00157 c = d + ROT_LEFT((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16);
00158 b = c + ROT_LEFT((b + H(c, d, a) + X[2] + 0xc4ac5665), 23);
00159
00160
00161 a = b + ROT_LEFT((a + I(b, c, d) + X[0] + 0xf4292244), 6);
00162 d = a + ROT_LEFT((d + I(a, b, c) + X[7] + 0x432aff97), 10);
00163 c = d + ROT_LEFT((c + I(d, a, b) + X[14] + 0xab9423a7), 15);
00164 b = c + ROT_LEFT((b + I(c, d, a) + X[5] + 0xfc93a039), 21);
00165 a = b + ROT_LEFT((a + I(b, c, d) + X[12] + 0x655b59c3), 6);
00166 d = a + ROT_LEFT((d + I(a, b, c) + X[3] + 0x8f0ccc92), 10);
00167 c = d + ROT_LEFT((c + I(d, a, b) + X[10] + 0xffeff47d), 15);
00168 b = c + ROT_LEFT((b + I(c, d, a) + X[1] + 0x85845dd1), 21);
00169 a = b + ROT_LEFT((a + I(b, c, d) + X[8] + 0x6fa87e4f), 6);
00170 d = a + ROT_LEFT((d + I(a, b, c) + X[15] + 0xfe2ce6e0), 10);
00171 c = d + ROT_LEFT((c + I(d, a, b) + X[6] + 0xa3014314), 15);
00172 b = c + ROT_LEFT((b + I(c, d, a) + X[13] + 0x4e0811a1), 21);
00173 a = b + ROT_LEFT((a + I(b, c, d) + X[4] + 0xf7537e82), 6);
00174 d = a + ROT_LEFT((d + I(a, b, c) + X[11] + 0xbd3af235), 10);
00175 c = d + ROT_LEFT((c + I(d, a, b) + X[2] + 0x2ad7d2bb), 15);
00176 b = c + ROT_LEFT((b + I(c, d, a) + X[9] + 0xeb86d391), 21);
00177
00178 state[0] += a;
00179 state[1] += b;
00180 state[2] += c;
00181 state[3] += d;
00182 }
00183
00184 static int
00185 calculateDigestFromBuffer(const uint8 *b, uint32 len, uint8 sum[16])
00186 {
00187 register uint32 i,
00188 j,
00189 k,
00190 newI;
00191 uint32 l;
00192 uint8 *input;
00193 register uint32 *wbp;
00194 uint32 workBuff[16],
00195 state[4];
00196
00197 l = len;
00198
00199 state[0] = 0x67452301;
00200 state[1] = 0xEFCDAB89;
00201 state[2] = 0x98BADCFE;
00202 state[3] = 0x10325476;
00203
00204 if ((input = createPaddedCopyWithLength(b, &l)) == NULL)
00205 return 0;
00206
00207 for (i = 0;;)
00208 {
00209 if ((newI = i + 16 * 4) > l)
00210 break;
00211 k = i + 3;
00212 for (j = 0; j < 16; j++)
00213 {
00214 wbp = (workBuff + j);
00215 *wbp = input[k--];
00216 *wbp <<= 8;
00217 *wbp |= input[k--];
00218 *wbp <<= 8;
00219 *wbp |= input[k--];
00220 *wbp <<= 8;
00221 *wbp |= input[k];
00222 k += 7;
00223 }
00224 doTheRounds(workBuff, state);
00225 i = newI;
00226 }
00227 free(input);
00228
00229 j = 0;
00230 for (i = 0; i < 4; i++)
00231 {
00232 k = state[i];
00233 sum[j++] = (k & 0xff);
00234 k >>= 8;
00235 sum[j++] = (k & 0xff);
00236 k >>= 8;
00237 sum[j++] = (k & 0xff);
00238 k >>= 8;
00239 sum[j++] = (k & 0xff);
00240 }
00241 return 1;
00242 }
00243
00244 static void
00245 bytesToHex(uint8 b[16], char *s)
00246 {
00247 static const char *hex = "0123456789abcdef";
00248 int q,
00249 w;
00250
00251 for (q = 0, w = 0; q < 16; q++)
00252 {
00253 s[w++] = hex[(b[q] >> 4) & 0x0F];
00254 s[w++] = hex[b[q] & 0x0F];
00255 }
00256 s[w] = '\0';
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 bool
00290 pg_md5_hash(const void *buff, size_t len, char *hexsum)
00291 {
00292 uint8 sum[16];
00293
00294 if (!calculateDigestFromBuffer(buff, len, sum))
00295 return false;
00296
00297 bytesToHex(sum, hexsum);
00298 return true;
00299 }
00300
00301 bool
00302 pg_md5_binary(const void *buff, size_t len, void *outbuf)
00303 {
00304 if (!calculateDigestFromBuffer(buff, len, outbuf))
00305 return false;
00306 return true;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 bool
00320 pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
00321 char *buf)
00322 {
00323 size_t passwd_len = strlen(passwd);
00324
00325
00326 char *crypt_buf = malloc(passwd_len + salt_len + 1);
00327 bool ret;
00328
00329 if (!crypt_buf)
00330 return false;
00331
00332
00333
00334
00335
00336 memcpy(crypt_buf, passwd, passwd_len);
00337 memcpy(crypt_buf + passwd_len, salt, salt_len);
00338
00339 strcpy(buf, "md5");
00340 ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
00341
00342 free(crypt_buf);
00343
00344 return ret;
00345 }