diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/Makefile | 3 | ||||
-rw-r--r-- | src/common/cryptohash.c | 13 | ||||
-rw-r--r-- | src/common/cryptohash_openssl.c | 3 | ||||
-rw-r--r-- | src/common/md5.c | 683 | ||||
-rw-r--r-- | src/common/md5_common.c | 149 | ||||
-rw-r--r-- | src/common/md5_int.h | 85 | ||||
-rw-r--r-- | src/include/common/cryptohash.h | 3 | ||||
-rw-r--r-- | src/include/common/md5.h | 5 | ||||
-rw-r--r-- | src/tools/msvc/Mkvcbuild.pm | 12 | ||||
-rw-r--r-- | src/tools/pgindent/typedefs.list | 1 |
10 files changed, 651 insertions, 306 deletions
diff --git a/src/common/Makefile b/src/common/Makefile index b8f51872826..af891cb0cea 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -63,7 +63,7 @@ OBJS_COMMON = \ keywords.o \ kwlookup.o \ link-canary.o \ - md5.o \ + md5_common.o \ pg_get_line.o \ pg_lzcompress.o \ pgfnames.o \ @@ -86,6 +86,7 @@ OBJS_COMMON += \ else OBJS_COMMON += \ cryptohash.o \ + md5.o \ sha2.o endif diff --git a/src/common/cryptohash.c b/src/common/cryptohash.c index a61091f456e..5cc2572eb6e 100644 --- a/src/common/cryptohash.c +++ b/src/common/cryptohash.c @@ -24,6 +24,7 @@ #include <sys/param.h> #include "common/cryptohash.h" +#include "md5_int.h" #include "sha2_int.h" /* @@ -57,6 +58,9 @@ pg_cryptohash_create(pg_cryptohash_type type) switch (type) { + case PG_MD5: + ctx->data = ALLOC(sizeof(pg_md5_ctx)); + break; case PG_SHA224: ctx->data = ALLOC(sizeof(pg_sha224_ctx)); break; @@ -95,6 +99,9 @@ pg_cryptohash_init(pg_cryptohash_ctx *ctx) switch (ctx->type) { + case PG_MD5: + pg_md5_init((pg_md5_ctx *) ctx->data); + break; case PG_SHA224: pg_sha224_init((pg_sha224_ctx *) ctx->data); break; @@ -126,6 +133,9 @@ pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len) switch (ctx->type) { + case PG_MD5: + pg_md5_update((pg_md5_ctx *) ctx->data, data, len); + break; case PG_SHA224: pg_sha224_update((pg_sha224_ctx *) ctx->data, data, len); break; @@ -157,6 +167,9 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest) switch (ctx->type) { + case PG_MD5: + pg_md5_final((pg_md5_ctx *) ctx->data, dest); + break; case PG_SHA224: pg_sha224_final((pg_sha224_ctx *) ctx->data, dest); break; diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c index 9d9f74b086c..118651c4153 100644 --- a/src/common/cryptohash_openssl.c +++ b/src/common/cryptohash_openssl.c @@ -135,6 +135,9 @@ pg_cryptohash_init(pg_cryptohash_ctx *ctx) switch (ctx->type) { + case PG_MD5: + status = EVP_DigestInit_ex(state->evpctx, EVP_md5(), NULL); + break; case PG_SHA224: status = EVP_DigestInit_ex(state->evpctx, EVP_sha224(), NULL); break; diff --git a/src/common/md5.c b/src/common/md5.c index 5f790c6800e..ab761560944 100644 --- a/src/common/md5.c +++ b/src/common/md5.c @@ -1,20 +1,50 @@ -/* - * md5.c +/*------------------------------------------------------------------------- * - * Implements the MD5 Message-Digest Algorithm as specified in - * RFC 1321. This implementation is a simple one, in that it - * needs every input byte to be buffered before doing any - * calculations. I do not expect this file to be used for - * general purpose MD5'ing of large amounts of data, only for - * generating hashed passwords from limited input. + * md5.c + * Implements the MD5 Message-Digest Algorithm * - * Sverre H. Huseby <sverrehu@online.no> + * Fallback implementation of MD5, as specified in RFC 1321. This + * implementation is a simple one, in that it needs every input byte + * to be buffered before doing any calculations. * * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * src/common/md5.c + * + *------------------------------------------------------------------------- + */ + +/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef FRONTEND @@ -23,326 +53,387 @@ #include "postgres_fe.h" #endif -#include "common/md5.h" - +#include "md5_int.h" + +#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s)))) + +#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) +#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z))) +#define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) +#define I(X, Y, Z) ((Y) ^ ((X) | (~Z))) + +#define ROUND1(a, b, c, d, k, s, i) \ +do { \ + (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ +} while (0) + +#define ROUND2(a, b, c, d, k, s, i) \ +do { \ + (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ +} while (0) + +#define ROUND3(a, b, c, d, k, s, i) \ +do { \ + (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ +} while (0) + +#define ROUND4(a, b, c, d, k, s, i) \ +do { \ + (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ +} while (0) + +#define Sa 7 +#define Sb 12 +#define Sc 17 +#define Sd 22 + +#define Se 5 +#define Sf 9 +#define Sg 14 +#define Sh 20 + +#define Si 4 +#define Sj 11 +#define Sk 16 +#define Sl 23 + +#define Sm 6 +#define Sn 10 +#define So 15 +#define Sp 21 + +#define MD5_A0 0x67452301 +#define MD5_B0 0xefcdab89 +#define MD5_C0 0x98badcfe +#define MD5_D0 0x10325476 + +/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */ +static const uint32 T[65] = { + 0, + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, +}; + +static const uint8 md5_paddat[MD5_BUFLEN] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#ifdef WORDS_BIGENDIAN +static uint32 X[16]; +#endif -/* - * PRIVATE FUNCTIONS - */ +static void +md5_calc(const uint8 *b64, pg_md5_ctx *ctx) +{ + uint32 A = ctx->md5_sta; + uint32 B = ctx->md5_stb; + uint32 C = ctx->md5_stc; + uint32 D = ctx->md5_std; +#ifndef WORDS_BIGENDIAN + const uint32 *X = (const uint32 *) b64; +#else + /* 4 byte words */ + /* what a brute force but fast! */ + uint8 *y = (uint8 *) X; + + y[0] = b64[3]; + y[1] = b64[2]; + y[2] = b64[1]; + y[3] = b64[0]; + y[4] = b64[7]; + y[5] = b64[6]; + y[6] = b64[5]; + y[7] = b64[4]; + y[8] = b64[11]; + y[9] = b64[10]; + y[10] = b64[9]; + y[11] = b64[8]; + y[12] = b64[15]; + y[13] = b64[14]; + y[14] = b64[13]; + y[15] = b64[12]; + y[16] = b64[19]; + y[17] = b64[18]; + y[18] = b64[17]; + y[19] = b64[16]; + y[20] = b64[23]; + y[21] = b64[22]; + y[22] = b64[21]; + y[23] = b64[20]; + y[24] = b64[27]; + y[25] = b64[26]; + y[26] = b64[25]; + y[27] = b64[24]; + y[28] = b64[31]; + y[29] = b64[30]; + y[30] = b64[29]; + y[31] = b64[28]; + y[32] = b64[35]; + y[33] = b64[34]; + y[34] = b64[33]; + y[35] = b64[32]; + y[36] = b64[39]; + y[37] = b64[38]; + y[38] = b64[37]; + y[39] = b64[36]; + y[40] = b64[43]; + y[41] = b64[42]; + y[42] = b64[41]; + y[43] = b64[40]; + y[44] = b64[47]; + y[45] = b64[46]; + y[46] = b64[45]; + y[47] = b64[44]; + y[48] = b64[51]; + y[49] = b64[50]; + y[50] = b64[49]; + y[51] = b64[48]; + y[52] = b64[55]; + y[53] = b64[54]; + y[54] = b64[53]; + y[55] = b64[52]; + y[56] = b64[59]; + y[57] = b64[58]; + y[58] = b64[57]; + y[59] = b64[56]; + y[60] = b64[63]; + y[61] = b64[62]; + y[62] = b64[61]; + y[63] = b64[60]; +#endif -/* - * The returned array is allocated using malloc. the caller should free it - * when it is no longer needed. - */ -static uint8 * -createPaddedCopyWithLength(const uint8 *b, uint32 *l) -{ - uint8 *ret; - uint32 q; - uint32 len, - newLen448; - uint32 len_high, - len_low; /* 64-bit value split into 32-bit sections */ - - len = ((b == NULL) ? 0 : *l); - newLen448 = len + 64 - (len % 64) - 8; - if (newLen448 <= len) - newLen448 += 64; - - *l = newLen448 + 8; - if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL) - return NULL; - - if (b != NULL) - memcpy(ret, b, sizeof(uint8) * len); - - /* pad */ - ret[len] = 0x80; - for (q = len + 1; q < newLen448; q++) - ret[q] = 0x00; - - /* append length as a 64 bit bitcount */ - len_low = len; - /* split into two 32-bit values */ - /* we only look at the bottom 32-bits */ - len_high = len >> 29; - len_low <<= 3; - q = newLen448; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q] = (len_high & 0xff); - - return ret; + ROUND1(A, B, C, D, 0, Sa, 1); + ROUND1(D, A, B, C, 1, Sb, 2); + ROUND1(C, D, A, B, 2, Sc, 3); + ROUND1(B, C, D, A, 3, Sd, 4); + ROUND1(A, B, C, D, 4, Sa, 5); + ROUND1(D, A, B, C, 5, Sb, 6); + ROUND1(C, D, A, B, 6, Sc, 7); + ROUND1(B, C, D, A, 7, Sd, 8); + ROUND1(A, B, C, D, 8, Sa, 9); + ROUND1(D, A, B, C, 9, Sb, 10); + ROUND1(C, D, A, B, 10, Sc, 11); + ROUND1(B, C, D, A, 11, Sd, 12); + ROUND1(A, B, C, D, 12, Sa, 13); + ROUND1(D, A, B, C, 13, Sb, 14); + ROUND1(C, D, A, B, 14, Sc, 15); + ROUND1(B, C, D, A, 15, Sd, 16); + + ROUND2(A, B, C, D, 1, Se, 17); + ROUND2(D, A, B, C, 6, Sf, 18); + ROUND2(C, D, A, B, 11, Sg, 19); + ROUND2(B, C, D, A, 0, Sh, 20); + ROUND2(A, B, C, D, 5, Se, 21); + ROUND2(D, A, B, C, 10, Sf, 22); + ROUND2(C, D, A, B, 15, Sg, 23); + ROUND2(B, C, D, A, 4, Sh, 24); + ROUND2(A, B, C, D, 9, Se, 25); + ROUND2(D, A, B, C, 14, Sf, 26); + ROUND2(C, D, A, B, 3, Sg, 27); + ROUND2(B, C, D, A, 8, Sh, 28); + ROUND2(A, B, C, D, 13, Se, 29); + ROUND2(D, A, B, C, 2, Sf, 30); + ROUND2(C, D, A, B, 7, Sg, 31); + ROUND2(B, C, D, A, 12, Sh, 32); + + ROUND3(A, B, C, D, 5, Si, 33); + ROUND3(D, A, B, C, 8, Sj, 34); + ROUND3(C, D, A, B, 11, Sk, 35); + ROUND3(B, C, D, A, 14, Sl, 36); + ROUND3(A, B, C, D, 1, Si, 37); + ROUND3(D, A, B, C, 4, Sj, 38); + ROUND3(C, D, A, B, 7, Sk, 39); + ROUND3(B, C, D, A, 10, Sl, 40); + ROUND3(A, B, C, D, 13, Si, 41); + ROUND3(D, A, B, C, 0, Sj, 42); + ROUND3(C, D, A, B, 3, Sk, 43); + ROUND3(B, C, D, A, 6, Sl, 44); + ROUND3(A, B, C, D, 9, Si, 45); + ROUND3(D, A, B, C, 12, Sj, 46); + ROUND3(C, D, A, B, 15, Sk, 47); + ROUND3(B, C, D, A, 2, Sl, 48); + + ROUND4(A, B, C, D, 0, Sm, 49); + ROUND4(D, A, B, C, 7, Sn, 50); + ROUND4(C, D, A, B, 14, So, 51); + ROUND4(B, C, D, A, 5, Sp, 52); + ROUND4(A, B, C, D, 12, Sm, 53); + ROUND4(D, A, B, C, 3, Sn, 54); + ROUND4(C, D, A, B, 10, So, 55); + ROUND4(B, C, D, A, 1, Sp, 56); + ROUND4(A, B, C, D, 8, Sm, 57); + ROUND4(D, A, B, C, 15, Sn, 58); + ROUND4(C, D, A, B, 6, So, 59); + ROUND4(B, C, D, A, 13, Sp, 60); + ROUND4(A, B, C, D, 4, Sm, 61); + ROUND4(D, A, B, C, 11, Sn, 62); + ROUND4(C, D, A, B, 2, So, 63); + ROUND4(B, C, D, A, 9, Sp, 64); + + ctx->md5_sta += A; + ctx->md5_stb += B; + ctx->md5_stc += C; + ctx->md5_std += D; } -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define ROT_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - static void -doTheRounds(uint32 X[16], uint32 state[4]) +md5_pad(pg_md5_ctx *ctx) { - uint32 a, - b, - c, - d; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - - /* round 1 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[0] + 0xd76aa478), 7); /* 1 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[1] + 0xe8c7b756), 12); /* 2 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[2] + 0x242070db), 17); /* 3 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[3] + 0xc1bdceee), 22); /* 4 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[4] + 0xf57c0faf), 7); /* 5 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[5] + 0x4787c62a), 12); /* 6 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[6] + 0xa8304613), 17); /* 7 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[7] + 0xfd469501), 22); /* 8 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[8] + 0x698098d8), 7); /* 9 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[9] + 0x8b44f7af), 12); /* 10 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[10] + 0xffff5bb1), 17); /* 11 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[11] + 0x895cd7be), 22); /* 12 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[12] + 0x6b901122), 7); /* 13 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[13] + 0xfd987193), 12); /* 14 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[14] + 0xa679438e), 17); /* 15 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[15] + 0x49b40821), 22); /* 16 */ - - /* round 2 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[1] + 0xf61e2562), 5); /* 17 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[6] + 0xc040b340), 9); /* 18 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[11] + 0x265e5a51), 14); /* 19 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[0] + 0xe9b6c7aa), 20); /* 20 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[5] + 0xd62f105d), 5); /* 21 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[10] + 0x02441453), 9); /* 22 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[15] + 0xd8a1e681), 14); /* 23 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[4] + 0xe7d3fbc8), 20); /* 24 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[9] + 0x21e1cde6), 5); /* 25 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[14] + 0xc33707d6), 9); /* 26 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[3] + 0xf4d50d87), 14); /* 27 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[8] + 0x455a14ed), 20); /* 28 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[13] + 0xa9e3e905), 5); /* 29 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[2] + 0xfcefa3f8), 9); /* 30 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[7] + 0x676f02d9), 14); /* 31 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20); /* 32 */ - - /* round 3 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[5] + 0xfffa3942), 4); /* 33 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[8] + 0x8771f681), 11); /* 34 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[11] + 0x6d9d6122), 16); /* 35 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[14] + 0xfde5380c), 23); /* 36 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[1] + 0xa4beea44), 4); /* 37 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[4] + 0x4bdecfa9), 11); /* 38 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[7] + 0xf6bb4b60), 16); /* 39 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[10] + 0xbebfbc70), 23); /* 40 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[13] + 0x289b7ec6), 4); /* 41 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[0] + 0xeaa127fa), 11); /* 42 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[3] + 0xd4ef3085), 16); /* 43 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[6] + 0x04881d05), 23); /* 44 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[9] + 0xd9d4d039), 4); /* 45 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[12] + 0xe6db99e5), 11); /* 46 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16); /* 47 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[2] + 0xc4ac5665), 23); /* 48 */ - - /* round 4 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[0] + 0xf4292244), 6); /* 49 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[7] + 0x432aff97), 10); /* 50 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[14] + 0xab9423a7), 15); /* 51 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[5] + 0xfc93a039), 21); /* 52 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[12] + 0x655b59c3), 6); /* 53 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[3] + 0x8f0ccc92), 10); /* 54 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[10] + 0xffeff47d), 15); /* 55 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[1] + 0x85845dd1), 21); /* 56 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[8] + 0x6fa87e4f), 6); /* 57 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[15] + 0xfe2ce6e0), 10); /* 58 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[6] + 0xa3014314), 15); /* 59 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[13] + 0x4e0811a1), 21); /* 60 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[4] + 0xf7537e82), 6); /* 61 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[11] + 0xbd3af235), 10); /* 62 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[2] + 0x2ad7d2bb), 15); /* 63 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[9] + 0xeb86d391), 21); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} + unsigned int gap; -static int -calculateDigestFromBuffer(const uint8 *b, uint32 len, uint8 sum[16]) -{ - register uint32 i, - j, - k, - newI; - uint32 l; - uint8 *input; - register uint32 *wbp; - uint32 workBuff[16], - state[4]; - - l = len; - - state[0] = 0x67452301; - state[1] = 0xEFCDAB89; - state[2] = 0x98BADCFE; - state[3] = 0x10325476; - - if ((input = createPaddedCopyWithLength(b, &l)) == NULL) - return 0; - - for (i = 0;;) + /* Don't count up padding. Keep md5_n. */ + gap = MD5_BUFLEN - ctx->md5_i; + if (gap > 8) { - if ((newI = i + 16 * 4) > l) - break; - k = i + 3; - for (j = 0; j < 16; j++) - { - wbp = (workBuff + j); - *wbp = input[k--]; - *wbp <<= 8; - *wbp |= input[k--]; - *wbp <<= 8; - *wbp |= input[k--]; - *wbp <<= 8; - *wbp |= input[k]; - k += 7; - } - doTheRounds(workBuff, state); - i = newI; + memmove(ctx->md5_buf + ctx->md5_i, md5_paddat, + gap - sizeof(ctx->md5_n)); } - free(input); - - j = 0; - for (i = 0; i < 4; i++) + else { - k = state[i]; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); + /* including gap == 8 */ + memmove(ctx->md5_buf + ctx->md5_i, md5_paddat, gap); + md5_calc(ctx->md5_buf, ctx); + memmove(ctx->md5_buf, md5_paddat + gap, + MD5_BUFLEN - sizeof(ctx->md5_n)); } - return 1; + + /* 8 byte word */ +#ifndef WORDS_BIGENDIAN + memmove(&ctx->md5_buf[56], &ctx->md5_n8[0], 8); +#else + ctx->md5_buf[56] = ctx->md5_n8[7]; + ctx->md5_buf[57] = ctx->md5_n8[6]; + ctx->md5_buf[58] = ctx->md5_n8[5]; + ctx->md5_buf[59] = ctx->md5_n8[4]; + ctx->md5_buf[60] = ctx->md5_n8[3]; + ctx->md5_buf[61] = ctx->md5_n8[2]; + ctx->md5_buf[62] = ctx->md5_n8[1]; + ctx->md5_buf[63] = ctx->md5_n8[0]; +#endif + + md5_calc(ctx->md5_buf, ctx); } static void -bytesToHex(uint8 b[16], char *s) +md5_result(uint8 *digest, pg_md5_ctx *ctx) { - static const char *hex = "0123456789abcdef"; - int q, - w; - - for (q = 0, w = 0; q < 16; q++) - { - s[w++] = hex[(b[q] >> 4) & 0x0F]; - s[w++] = hex[b[q] & 0x0F]; - } - s[w] = '\0'; + /* 4 byte words */ +#ifndef WORDS_BIGENDIAN + memmove(digest, &ctx->md5_st8[0], 16); +#else + digest[0] = ctx->md5_st8[3]; + digest[1] = ctx->md5_st8[2]; + digest[2] = ctx->md5_st8[1]; + digest[3] = ctx->md5_st8[0]; + digest[4] = ctx->md5_st8[7]; + digest[5] = ctx->md5_st8[6]; + digest[6] = ctx->md5_st8[5]; + digest[7] = ctx->md5_st8[4]; + digest[8] = ctx->md5_st8[11]; + digest[9] = ctx->md5_st8[10]; + digest[10] = ctx->md5_st8[9]; + digest[11] = ctx->md5_st8[8]; + digest[12] = ctx->md5_st8[15]; + digest[13] = ctx->md5_st8[14]; + digest[14] = ctx->md5_st8[13]; + digest[15] = ctx->md5_st8[12]; +#endif } -/* - * PUBLIC FUNCTIONS - */ + +/* External routines for this MD5 implementation */ /* - * pg_md5_hash - * - * Calculates the MD5 sum of the bytes in a buffer. - * - * SYNOPSIS #include "md5.h" - * int pg_md5_hash(const void *buff, size_t len, char *hexsum) - * - * INPUT buff the buffer containing the bytes that you want - * the MD5 sum of. - * len number of bytes in the buffer. - * - * OUTPUT hexsum the MD5 sum as a '\0'-terminated string of - * hexadecimal digits. an MD5 sum is 16 bytes long. - * each byte is represented by two hexadecimal - * characters. you thus need to provide an array - * of 33 characters, including the trailing '\0'. - * - * RETURNS false on failure (out of memory for internal buffers) or - * true on success. - * - * STANDARDS MD5 is described in RFC 1321. - * - * AUTHOR Sverre H. Huseby <sverrehu@online.no> + * pg_md5_init * + * Initialize a MD5 context. */ -bool -pg_md5_hash(const void *buff, size_t len, char *hexsum) -{ - uint8 sum[16]; - - if (!calculateDigestFromBuffer(buff, len, sum)) - return false; - - bytesToHex(sum, hexsum); - return true; -} - -bool -pg_md5_binary(const void *buff, size_t len, void *outbuf) +void +pg_md5_init(pg_md5_ctx *ctx) { - if (!calculateDigestFromBuffer(buff, len, outbuf)) - return false; - return true; + ctx->md5_n = 0; + ctx->md5_i = 0; + ctx->md5_sta = MD5_A0; + ctx->md5_stb = MD5_B0; + ctx->md5_stc = MD5_C0; + ctx->md5_std = MD5_D0; + memset(ctx->md5_buf, 0, sizeof(ctx->md5_buf)); } /* - * Computes MD5 checksum of "passwd" (a null-terminated string) followed - * by "salt" (which need not be null-terminated). + * pg_md5_update * - * Output format is "md5" followed by a 32-hex-digit MD5 checksum. - * Hence, the output buffer "buf" must be at least 36 bytes long. - * - * Returns true if okay, false on error (out of memory). + * Update a MD5 context. */ -bool -pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, - char *buf) +void +pg_md5_update(pg_md5_ctx *ctx, const uint8 *data, size_t len) { - size_t passwd_len = strlen(passwd); - - /* +1 here is just to avoid risk of unportable malloc(0) */ - char *crypt_buf = malloc(passwd_len + salt_len + 1); - bool ret; + unsigned int gap, + i; - if (!crypt_buf) - return false; + ctx->md5_n += len * 8; /* byte to bit */ + gap = MD5_BUFLEN - ctx->md5_i; - /* - * Place salt at the end because it may be known by users trying to crack - * the MD5 output. - */ - memcpy(crypt_buf, passwd, passwd_len); - memcpy(crypt_buf + passwd_len, salt, salt_len); + if (len >= gap) + { + memmove(ctx->md5_buf + ctx->md5_i, data, gap); + md5_calc(ctx->md5_buf, ctx); - strcpy(buf, "md5"); - ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3); + for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) + md5_calc(data + i, ctx); - free(crypt_buf); + ctx->md5_i = len - i; + memmove(ctx->md5_buf, data + i, ctx->md5_i); + } + else + { + memmove(ctx->md5_buf + ctx->md5_i, data, len); + ctx->md5_i += len; + } +} - return ret; +/* + * pg_md5_final + * + * Finalize a MD5 context. + */ +void +pg_md5_final(pg_md5_ctx *ctx, uint8 *dest) +{ + md5_pad(ctx); + md5_result(dest, ctx); } diff --git a/src/common/md5_common.c b/src/common/md5_common.c new file mode 100644 index 00000000000..74c274175fe --- /dev/null +++ b/src/common/md5_common.c @@ -0,0 +1,149 @@ +/*------------------------------------------------------------------------- + * + * md5_common.c + * Routines shared between all MD5 implementations used for encrypted + * passwords. + * + * Sverre H. Huseby <sverrehu@online.no> + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/common/md5_common.c + * + *------------------------------------------------------------------------- + */ + +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#include "common/cryptohash.h" +#include "common/md5.h" + +static void +bytesToHex(uint8 b[16], char *s) +{ + static const char *hex = "0123456789abcdef"; + int q, + w; + + for (q = 0, w = 0; q < 16; q++) + { + s[w++] = hex[(b[q] >> 4) & 0x0F]; + s[w++] = hex[b[q] & 0x0F]; + } + s[w] = '\0'; +} + +/* + * pg_md5_hash + * + * Calculates the MD5 sum of the bytes in a buffer. + * + * SYNOPSIS #include "md5.h" + * int pg_md5_hash(const void *buff, size_t len, char *hexsum) + * + * INPUT buff the buffer containing the bytes that you want + * the MD5 sum of. + * len number of bytes in the buffer. + * + * OUTPUT hexsum the MD5 sum as a '\0'-terminated string of + * hexadecimal digits. an MD5 sum is 16 bytes long. + * each byte is represented by two hexadecimal + * characters. you thus need to provide an array + * of 33 characters, including the trailing '\0'. + * + * RETURNS false on failure (out of memory for internal buffers + * or MD5 computation failure) or true on success. + * + * STANDARDS MD5 is described in RFC 1321. + * + * AUTHOR Sverre H. Huseby <sverrehu@online.no> + * + */ + +bool +pg_md5_hash(const void *buff, size_t len, char *hexsum) +{ + uint8 sum[16]; + pg_cryptohash_ctx *ctx; + + ctx = pg_cryptohash_create(PG_MD5); + if (ctx == NULL) + return false; + + if (pg_cryptohash_init(ctx) < 0 || + pg_cryptohash_update(ctx, buff, len) < 0 || + pg_cryptohash_final(ctx, sum) < 0) + { + pg_cryptohash_free(ctx); + return false; + } + + bytesToHex(sum, hexsum); + pg_cryptohash_free(ctx); + return true; +} + +bool +pg_md5_binary(const void *buff, size_t len, void *outbuf) +{ + pg_cryptohash_ctx *ctx; + + ctx = pg_cryptohash_create(PG_MD5); + if (ctx == NULL) + return false; + + if (pg_cryptohash_init(ctx) < 0 || + pg_cryptohash_update(ctx, buff, len) < 0 || + pg_cryptohash_final(ctx, outbuf) < 0) + { + pg_cryptohash_free(ctx); + return false; + } + + pg_cryptohash_free(ctx); + return true; +} + + +/* + * Computes MD5 checksum of "passwd" (a null-terminated string) followed + * by "salt" (which need not be null-terminated). + * + * Output format is "md5" followed by a 32-hex-digit MD5 checksum. + * Hence, the output buffer "buf" must be at least 36 bytes long. + * + * Returns true if okay, false on error (out of memory). + */ +bool +pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, + char *buf) +{ + size_t passwd_len = strlen(passwd); + + /* +1 here is just to avoid risk of unportable malloc(0) */ + char *crypt_buf = malloc(passwd_len + salt_len + 1); + bool ret; + + if (!crypt_buf) + return false; + + /* + * Place salt at the end because it may be known by users trying to crack + * the MD5 output. + */ + memcpy(crypt_buf, passwd, passwd_len); + memcpy(crypt_buf + passwd_len, salt, salt_len); + + strcpy(buf, "md5"); + ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3); + + free(crypt_buf); + + return ret; +} diff --git a/src/common/md5_int.h b/src/common/md5_int.h new file mode 100644 index 00000000000..b5b71e2582f --- /dev/null +++ b/src/common/md5_int.h @@ -0,0 +1,85 @@ +/*------------------------------------------------------------------------- + * + * md5_int.h + * Internal headers for fallback implementation of MD5 + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/common/md5_int.h + * + *------------------------------------------------------------------------- + */ + +/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PG_MD5_INT_H +#define PG_MD5_INT_H + +#include "common/md5.h" + +#define MD5_BUFLEN 64 + +/* Context data for MD5 */ +typedef struct +{ + union + { + uint32 md5_state32[4]; + uint8 md5_state8[16]; + } md5_st; + +#define md5_sta md5_st.md5_state32[0] +#define md5_stb md5_st.md5_state32[1] +#define md5_stc md5_st.md5_state32[2] +#define md5_std md5_st.md5_state32[3] +#define md5_st8 md5_st.md5_state8 + + union + { + uint64 md5_count64; + uint8 md5_count8[8]; + } md5_count; +#define md5_n md5_count.md5_count64 +#define md5_n8 md5_count.md5_count8 + + unsigned int md5_i; + uint8 md5_buf[MD5_BUFLEN]; +} pg_md5_ctx; + +/* Interface routines for MD5 */ +extern void pg_md5_init(pg_md5_ctx *ctx); +extern void pg_md5_update(pg_md5_ctx *ctx, const uint8 *data, size_t len); +extern void pg_md5_final(pg_md5_ctx *ctx, uint8 *dest); + +#endif /* PG_MD5_INT_H */ diff --git a/src/include/common/cryptohash.h b/src/include/common/cryptohash.h index 0e4a6631a38..6ead1cb8e5b 100644 --- a/src/include/common/cryptohash.h +++ b/src/include/common/cryptohash.h @@ -18,7 +18,8 @@ /* Context Structures for each hash function */ typedef enum { - PG_SHA224 = 0, + PG_MD5 = 0, + PG_SHA224, PG_SHA256, PG_SHA384, PG_SHA512 diff --git a/src/include/common/md5.h b/src/include/common/md5.h index 8695f10dffc..53036d2d17e 100644 --- a/src/include/common/md5.h +++ b/src/include/common/md5.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * * md5.h - * Interface to libpq/md5.c + * Constants and common utilities related to MD5. * * These definitions are needed by both frontend and backend code to work * with MD5-encrypted passwords. @@ -19,9 +19,10 @@ #define MD5_PASSWD_CHARSET "0123456789abcdef" #define MD5_PASSWD_LEN 35 +/* Utilities common to all the MD5 implementations, as of md5_common.c */ extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum); extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf); extern bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf); -#endif +#endif /* PG_MD5_H */ diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 720b55142b3..f92c14030dc 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -122,7 +122,7 @@ sub mkvcbuild archive.c base64.c checksum_helper.c config_info.c controldata_utils.c d2s.c encnames.c exec.c f2s.c file_perm.c file_utils.c hashfn.c ip.c jsonapi.c - keywords.c kwlookup.c link-canary.c md5.c + keywords.c kwlookup.c link-canary.c md5_common.c pg_get_line.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c wait_error.c wchar.c); @@ -135,6 +135,7 @@ sub mkvcbuild else { push(@pgcommonallfiles, 'cryptohash.c'); + push(@pgcommonallfiles, 'md5.c'); push(@pgcommonallfiles, 'sha2.c'); } @@ -464,11 +465,10 @@ sub mkvcbuild else { $pgcrypto->AddFiles( - 'contrib/pgcrypto', 'md5.c', - 'sha1.c', 'internal.c', - 'internal-sha2.c', 'blf.c', - 'rijndael.c', 'pgp-mpi-internal.c', - 'imath.c'); + 'contrib/pgcrypto', 'sha1.c', + 'internal.c', 'internal-sha2.c', + 'blf.c', 'rijndael.c', + 'pgp-mpi-internal.c', 'imath.c'); } $pgcrypto->AddReference($postgres); $pgcrypto->AddLibrary('ws2_32.lib'); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index cf63acbf6f3..a9dca717a6d 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3192,6 +3192,7 @@ pg_int64 pg_local_to_utf_combined pg_locale_t pg_mb_radix_tree +pg_md5_ctx pg_on_exit_callback pg_re_flags pg_saslprep_rc |