On Fri, Nov 06, 2020 at 04:34:34PM +0900, Michael Paquier wrote: > The attached patch set does a bit of rework to make the Postgres code > more consistent with OpenSSL, similarly to the work I did for all the > SHA2 implementations with EVP in [1]: > - 0001 is something stolen from the SHA2 set, adding to resowner.c > control of EVP contexts, so as it is possible to clean up anything > allocated by OpenSSL. > - 0002 is the central piece, that moves the duplicated > implementation. src/common/ and pgcrypto/ use the same code, but I > have reused pgcrypto as it was already doing the init/update/final > split similarly to PostgreSQL. New APIs are designed to control MD5 > contexts, similarly to the work done for SHA2. Upon using this patch, > note that pgcrypto+OpenSSL uses our in-core implementation instead of > OpenSSL's one, but that's fixed in 0003. We have a set of three > convenience routines used to generate MD5-hashed passwords, that I > have moved to a new file in src/common/md5_common.c, aimed at being > shared between all the implementations. > - 0003 adds the MD5 implementation based on OpenSSL's EVP, ending the > work.
The CF bot has been complaining on Windows and this issue is fixed in the attached. A refresh of src/tools/msvc for pgcrypto was just missing. -- Michael
From f81ff379f10bb18cb2a44607262d0f27050afc3e Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Thu, 5 Nov 2020 15:53:00 +0900 Subject: [PATCH v2 1/3] Add APIs to control EVP contexts for resource owners This will be used by a set of upcoming patches for EVP contexts with SHA2 and MD5. --- src/include/utils/resowner_private.h | 7 +++ src/backend/utils/resowner/resowner.c | 65 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/include/utils/resowner_private.h b/src/include/utils/resowner_private.h index a781a7a2aa..5ce6fcf882 100644 --- a/src/include/utils/resowner_private.h +++ b/src/include/utils/resowner_private.h @@ -95,4 +95,11 @@ extern void ResourceOwnerRememberJIT(ResourceOwner owner, extern void ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle); +/* support for EVP context management */ +extern void ResourceOwnerEnlargeEVP(ResourceOwner owner); +extern void ResourceOwnerRememberEVP(ResourceOwner owner, + Datum handle); +extern void ResourceOwnerForgetEVP(ResourceOwner owner, + Datum handle); + #endif /* RESOWNER_PRIVATE_H */ diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index 8bc2c4e9ea..1efb5e98b4 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -20,6 +20,10 @@ */ #include "postgres.h" +#ifdef USE_OPENSSL +#include <openssl/evp.h> +#endif + #include "common/hashfn.h" #include "jit/jit.h" #include "storage/bufmgr.h" @@ -128,6 +132,7 @@ typedef struct ResourceOwnerData ResourceArray filearr; /* open temporary files */ ResourceArray dsmarr; /* dynamic shmem segments */ ResourceArray jitarr; /* JIT contexts */ + ResourceArray evparr; /* EVP contexts */ /* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */ int nlocks; /* number of owned locks */ @@ -175,6 +180,7 @@ static void PrintTupleDescLeakWarning(TupleDesc tupdesc); static void PrintSnapshotLeakWarning(Snapshot snapshot); static void PrintFileLeakWarning(File file); static void PrintDSMLeakWarning(dsm_segment *seg); +static void PrintEVPLeakWarning(Datum handle); /***************************************************************************** @@ -444,6 +450,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name) ResourceArrayInit(&(owner->filearr), FileGetDatum(-1)); ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL)); ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL)); + ResourceArrayInit(&(owner->evparr), PointerGetDatum(NULL)); return owner; } @@ -553,6 +560,17 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, jit_release_context(context); } + + /* Ditto for EVP contexts */ + while (ResourceArrayGetAny(&(owner->evparr), &foundres)) + { + if (isCommit) + PrintEVPLeakWarning(foundres); +#ifdef USE_OPENSSL + EVP_MD_CTX_destroy((EVP_MD_CTX *) DatumGetPointer(foundres)); +#endif + ResourceOwnerForgetEVP(owner, foundres); + } } else if (phase == RESOURCE_RELEASE_LOCKS) { @@ -725,6 +743,7 @@ ResourceOwnerDelete(ResourceOwner owner) Assert(owner->filearr.nitems == 0); Assert(owner->dsmarr.nitems == 0); Assert(owner->jitarr.nitems == 0); + Assert(owner->evparr.nitems == 0); Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1); /* @@ -752,6 +771,7 @@ ResourceOwnerDelete(ResourceOwner owner) ResourceArrayFree(&(owner->filearr)); ResourceArrayFree(&(owner->dsmarr)); ResourceArrayFree(&(owner->jitarr)); + ResourceArrayFree(&(owner->evparr)); pfree(owner); } @@ -1370,3 +1390,48 @@ ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle) elog(ERROR, "JIT context %p is not owned by resource owner %s", DatumGetPointer(handle), owner->name); } + +/* + * Make sure there is room for at least one more entry in a ResourceOwner's + * EVP context reference array. + * + * This is separate from actually inserting an entry because if we run out of + * memory, it's critical to do so *before* acquiring the resource. + */ +void +ResourceOwnerEnlargeEVP(ResourceOwner owner) +{ + ResourceArrayEnlarge(&(owner->evparr)); +} + +/* + * Remember that an EVP context is owned by a ResourceOwner + * + * Caller must have previously done ResourceOwnerEnlargeEVP() + */ +void +ResourceOwnerRememberEVP(ResourceOwner owner, Datum handle) +{ + ResourceArrayAdd(&(owner->evparr), handle); +} + +/* + * Forget that an EVP context is owned by a ResourceOwner + */ +void +ResourceOwnerForgetEVP(ResourceOwner owner, Datum handle) +{ + if (!ResourceArrayRemove(&(owner->evparr), handle)) + elog(ERROR, "EVP context %p is not owned by resource owner %s", + DatumGetPointer(handle), owner->name); +} + +/* + * Debugging subroutine + */ +static void +PrintEVPLeakWarning(Datum handle) +{ + elog(WARNING, "EVP context reference leak: context %p still referenced", + DatumGetPointer(handle)); +} -- 2.29.2
From 53e99eceefdc240ae8e8921b5da7e0c5c4eceb54 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Tue, 10 Nov 2020 13:23:03 +0900 Subject: [PATCH v2 2/3] Refactor MD5 implementations in the tree This removes the duplicated MD5 implementations present in both src/common/ and contrib/pgcrypto/, reworking the MD5 interface to be similar to what OpenSSL provides. This will ease the work of a follow-up patch to make Postgres use OpenSSL EVP for MD5. The original APIs used for MD5-hashed passwords are moved to a separate file called md5_common.c, aimed at being shared between all MD5 implementations. --- src/include/common/md5.h | 13 +- src/common/Makefile | 1 + src/common/md5.c | 719 ++++++++++++++++++++++-------------- src/common/md5_common.c | 144 ++++++++ contrib/pgcrypto/Makefile | 2 +- contrib/pgcrypto/internal.c | 24 +- contrib/pgcrypto/md5.c | 397 -------------------- contrib/pgcrypto/md5.h | 79 ---- src/tools/msvc/Mkvcbuild.pm | 11 +- 9 files changed, 619 insertions(+), 771 deletions(-) create mode 100644 src/common/md5_common.c delete mode 100644 contrib/pgcrypto/md5.c delete mode 100644 contrib/pgcrypto/md5.h diff --git a/src/include/common/md5.h b/src/include/common/md5.h index 8695f10dff..7cd1eec559 100644 --- a/src/include/common/md5.h +++ b/src/include/common/md5.h @@ -1,10 +1,8 @@ /*------------------------------------------------------------------------- * * md5.h - * Interface to libpq/md5.c + * Interface to common/md5.c * - * These definitions are needed by both frontend and backend code to work - * with MD5-encrypted passwords. * * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California @@ -19,6 +17,15 @@ #define MD5_PASSWD_CHARSET "0123456789abcdef" #define MD5_PASSWD_LEN 35 +/* Interface for MD5 implementations */ +extern void *pg_md5_create(void); +extern void pg_md5_free(void *ctx); +/* These return 0 on success, or -1 on failure */ +extern int pg_md5_init(void *ctx); +extern int pg_md5_update(void *ctx, const uint8 *data, size_t len); +extern int pg_md5_final(void *ctx, uint8 *dest); + +/* Utilities common to all the 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, diff --git a/src/common/Makefile b/src/common/Makefile index 25c55bd642..69de65fab5 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -64,6 +64,7 @@ OBJS_COMMON = \ kwlookup.o \ link-canary.o \ md5.o \ + md5_common.o \ pg_get_line.o \ pg_lzcompress.o \ pgfnames.o \ diff --git a/src/common/md5.c b/src/common/md5.c index 5f790c6800..5b4b2d155e 100644 --- a/src/common/md5.c +++ b/src/common/md5.c @@ -17,6 +17,37 @@ * 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 #include "postgres.h" #else @@ -25,324 +56,466 @@ #include "common/md5.h" - /* - * PRIVATE FUNCTIONS + * In backend, use palloc/pfree to ease the error handling. In frontend, + * use malloc to be able to return a failure status back to the caller. */ +#ifndef FRONTEND +#define ALLOC(size) palloc(size) +#define FREE(ptr) pfree(ptr) +#else +#define ALLOC(size) malloc(size) +#define FREE(ptr) free(ptr) +#endif +#define MD5_BUFLEN 64 -/* - * 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) +/* internal context data for MD5 */ +typedef struct { - uint8 *ret; - uint32 q; - uint32 len, - newLen448; - uint32 len_high, - len_low; /* 64-bit value split into 32-bit sections */ + union + { + uint32 md5_state32[4]; + uint8 md5_state8[16]; + } md5_st; - len = ((b == NULL) ? 0 : *l); - newLen448 = len + 64 - (len % 64) - 8; - if (newLen448 <= len) - newLen448 += 64; +#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 - *l = newLen448 + 8; - if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL) - return NULL; + union + { + uint64 md5_count64; + uint8 md5_count8[8]; + } md5_count; +#define md5_n md5_count.md5_count64 +#define md5_n8 md5_count.md5_count8 - if (b != NULL) - memcpy(ret, b, sizeof(uint8) * len); + unsigned int md5_i; + uint8 md5_buf[MD5_BUFLEN]; +} md5_ctxt; - /* pad */ - ret[len] = 0x80; - for (q = len + 1; q < newLen448; q++) - ret[q] = 0x00; +#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s)))) - /* 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); +#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))) - return ret; -} +#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 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)))) +#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 static void -doTheRounds(uint32 X[16], uint32 state[4]) +md5_calc(const uint8 *b64, md5_ctxt *ctxt) { - uint32 a, - b, - c, - d; + uint32 A = ctxt->md5_sta; + uint32 B = ctxt->md5_stb; + uint32 C = ctxt->md5_stc; + uint32 D = ctxt->md5_std; - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; +#ifndef WORDS_BIGENDIAN + const uint32 *X = (const uint32 *) b64; +#else + /* 4 byte words */ + /* what a brute force but fast! */ + uint8 *y = (uint8 *) X; - /* 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 */ + 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 - /* 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 */ + 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); - /* 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 */ + 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); - /* 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 */ + 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); - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} + 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); -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;;) - { - 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; - } - free(input); - - j = 0; - for (i = 0; i < 4; i++) - { - 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); - } - return 1; + ctxt->md5_sta += A; + ctxt->md5_stb += B; + ctxt->md5_stc += C; + ctxt->md5_std += D; } static void -bytesToHex(uint8 b[16], char *s) +md5_pad(md5_ctxt *ctxt) { - static const char *hex = "0123456789abcdef"; - int q, - w; + unsigned int gap; - for (q = 0, w = 0; q < 16; q++) + /* Don't count up padding. Keep md5_n. */ + gap = MD5_BUFLEN - ctxt->md5_i; + if (gap > 8) { - s[w++] = hex[(b[q] >> 4) & 0x0F]; - s[w++] = hex[b[q] & 0x0F]; + memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, + gap - sizeof(ctxt->md5_n)); } - s[w] = '\0'; + else + { + /* including gap == 8 */ + memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); + md5_calc(ctxt->md5_buf, ctxt); + memmove(ctxt->md5_buf, md5_paddat + gap, + MD5_BUFLEN - sizeof(ctxt->md5_n)); + } + + /* 8 byte word */ +#ifndef WORDS_BIGENDIAN + memmove(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); +#else + ctxt->md5_buf[56] = ctxt->md5_n8[7]; + ctxt->md5_buf[57] = ctxt->md5_n8[6]; + ctxt->md5_buf[58] = ctxt->md5_n8[5]; + ctxt->md5_buf[59] = ctxt->md5_n8[4]; + ctxt->md5_buf[60] = ctxt->md5_n8[3]; + ctxt->md5_buf[61] = ctxt->md5_n8[2]; + ctxt->md5_buf[62] = ctxt->md5_n8[1]; + ctxt->md5_buf[63] = ctxt->md5_n8[0]; +#endif + + md5_calc(ctxt->md5_buf, ctxt); +} + +static void +md5_result(uint8 *digest, md5_ctxt *ctxt) +{ + /* 4 byte words */ +#ifndef WORDS_BIGENDIAN + memmove(digest, &ctxt->md5_st8[0], 16); +#else + digest[0] = ctxt->md5_st8[3]; + digest[1] = ctxt->md5_st8[2]; + digest[2] = ctxt->md5_st8[1]; + digest[3] = ctxt->md5_st8[0]; + digest[4] = ctxt->md5_st8[7]; + digest[5] = ctxt->md5_st8[6]; + digest[6] = ctxt->md5_st8[5]; + digest[7] = ctxt->md5_st8[4]; + digest[8] = ctxt->md5_st8[11]; + digest[9] = ctxt->md5_st8[10]; + digest[10] = ctxt->md5_st8[9]; + digest[11] = ctxt->md5_st8[8]; + digest[12] = ctxt->md5_st8[15]; + digest[13] = ctxt->md5_st8[14]; + digest[14] = ctxt->md5_st8[13]; + digest[15] = ctxt->md5_st8[12]; +#endif +} + + +/* External routines for this MD5 implementation */ + +/* + * pg_md5_create + * + * Allocate a MD5 context. Returns NULL on failure. + */ +void * +pg_md5_create(void) +{ + md5_ctxt *ctxt; + + ctxt = ALLOC(sizeof(md5_ctxt)); + memset(ctxt, 0, sizeof(md5_ctxt)); + return ctxt; } /* - * PUBLIC FUNCTIONS + * pg_md5_init + * + * Initialize a MD5 context. Note that this implementation is designed + * to never fail, so this always returns 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 - * true on success. - * - * STANDARDS MD5 is described in RFC 1321. - * - * AUTHOR Sverre H. Huseby <sverr...@online.no> - * - */ -bool -pg_md5_hash(const void *buff, size_t len, char *hexsum) +int +pg_md5_init(void *ctx) { - uint8 sum[16]; + md5_ctxt *ctxt = (md5_ctxt *) ctx; - if (!calculateDigestFromBuffer(buff, len, sum)) - return false; - - bytesToHex(sum, hexsum); - return true; -} - -bool -pg_md5_binary(const void *buff, size_t len, void *outbuf) -{ - if (!calculateDigestFromBuffer(buff, len, outbuf)) - return false; - return true; + ctxt->md5_n = 0; + ctxt->md5_i = 0; + ctxt->md5_sta = MD5_A0; + ctxt->md5_stb = MD5_B0; + ctxt->md5_stc = MD5_C0; + ctxt->md5_std = MD5_D0; + memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); + return 0; } /* - * 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. Note that this implementation is designed + * to never fail, so this always returns 0. */ -bool -pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, - char *buf) +int +pg_md5_update(void *ctx, const uint8 *data, size_t len) { - size_t passwd_len = strlen(passwd); + unsigned int gap, + i; + md5_ctxt *ctxt = (md5_ctxt *) ctx; - /* +1 here is just to avoid risk of unportable malloc(0) */ - char *crypt_buf = malloc(passwd_len + salt_len + 1); - bool ret; + ctxt->md5_n += len * 8; /* byte to bit */ + gap = MD5_BUFLEN - ctxt->md5_i; - if (!crypt_buf) - return false; + if (len >= gap) + { + memmove(ctxt->md5_buf + ctxt->md5_i, data, gap); + md5_calc(ctxt->md5_buf, ctxt); - /* - * 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); + for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) + md5_calc(data + i, ctxt); - strcpy(buf, "md5"); - ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3); + ctxt->md5_i = len - i; + memmove(ctxt->md5_buf, data + i, ctxt->md5_i); + } + else + { + memmove(ctxt->md5_buf + ctxt->md5_i, data, len); + ctxt->md5_i += len; + } - free(crypt_buf); - - return ret; + return 0; +} + +/* + * pg_md5_final + * + * Finalize a MD5 context. Note that this implementation is designed + * to never fail, so this always returns 0. + */ +int +pg_md5_final(void *ctx, uint8 *dest) +{ + md5_pad(ctx); + md5_result(dest, ctx); + + return 0; +} + +/* + * pg_md5_free + * + * Free a MD5 context. + */ +void +pg_md5_free(void *ctx) +{ + md5_ctxt *ctxt = (md5_ctxt *) ctx; + + explicit_bzero(ctxt, sizeof(md5_ctxt)); + FREE(ctx); } diff --git a/src/common/md5_common.c b/src/common/md5_common.c new file mode 100644 index 0000000000..1ecc832dab --- /dev/null +++ b/src/common/md5_common.c @@ -0,0 +1,144 @@ +/* + * md5_common.c + * + * Routines shared between all MD5 implementations used for MD5-encrypted + * passwords. + * + * 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/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 <sverr...@online.no> + * + */ + +bool +pg_md5_hash(const void *buff, size_t len, char *hexsum) +{ + uint8 sum[16]; + void *ctx; + + ctx = pg_md5_create(); + if (ctx == NULL) + return false; + + if (pg_md5_init(ctx) < 0 || + pg_md5_update(ctx, buff, len) < 0 || + pg_md5_final(ctx, sum) < 0) + { + pg_md5_free(ctx); + return false; + } + + bytesToHex(sum, hexsum); + pg_md5_free(ctx); + return true; +} + +bool +pg_md5_binary(const void *buff, size_t len, void *outbuf) +{ + void *ctx; + + ctx = pg_md5_create(); + if (ctx == NULL) + return false; + + if (pg_md5_init(ctx) < 0 || + pg_md5_update(ctx, buff, len) < 0 || + pg_md5_final(ctx, outbuf) < 0) + { + pg_md5_free(ctx); + return false; + } + + pg_md5_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/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index 61eabd2fc0..d881e85add 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -1,6 +1,6 @@ # contrib/pgcrypto/Makefile -INT_SRCS = md5.c sha1.c internal.c internal-sha2.c blf.c rijndael.c \ +INT_SRCS = sha1.c internal.c internal-sha2.c blf.c rijndael.c \ pgp-mpi-internal.c imath.c INT_TESTS = sha2 diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c index 06469d41c0..ef85128bde 100644 --- a/contrib/pgcrypto/internal.c +++ b/contrib/pgcrypto/internal.c @@ -34,11 +34,12 @@ #include <time.h> #include "blf.h" -#include "md5.h" #include "px.h" #include "rijndael.h" #include "sha1.h" +#include "common/md5.h" + #ifndef MD5_DIGEST_LENGTH #define MD5_DIGEST_LENGTH 16 #endif @@ -96,34 +97,33 @@ int_md5_block_len(PX_MD *h) static void int_md5_update(PX_MD *h, const uint8 *data, unsigned dlen) { - MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; + void *ctx = h->p.ptr; - MD5Update(ctx, data, dlen); + pg_md5_update(ctx, data, dlen); } static void int_md5_reset(PX_MD *h) { - MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; + void *ctx = h->p.ptr; - MD5Init(ctx); + pg_md5_init(ctx); } static void int_md5_finish(PX_MD *h, uint8 *dst) { - MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; + void *ctx = h->p.ptr; - MD5Final(dst, ctx); + pg_md5_final(ctx, dst); } static void int_md5_free(PX_MD *h) { - MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; + void *ctx = h->p.ptr; - px_memset(ctx, 0, sizeof(*ctx)); - pfree(ctx); + pg_md5_free(ctx); pfree(h); } @@ -180,9 +180,9 @@ int_sha1_free(PX_MD *h) static void init_md5(PX_MD *md) { - MD5_CTX *ctx; + void *ctx; - ctx = palloc0(sizeof(*ctx)); + ctx = pg_md5_create(); md->p.ptr = ctx; diff --git a/contrib/pgcrypto/md5.c b/contrib/pgcrypto/md5.c deleted file mode 100644 index 15d7c9bcdc..0000000000 --- a/contrib/pgcrypto/md5.c +++ /dev/null @@ -1,397 +0,0 @@ -/* $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. - * - * contrib/pgcrypto/md5.c - */ - -#include "postgres.h" - -#include <sys/param.h> - -#include "md5.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, -}; - -static void md5_calc(const uint8 *, md5_ctxt *); - -void -md5_init(md5_ctxt *ctxt) -{ - ctxt->md5_n = 0; - ctxt->md5_i = 0; - ctxt->md5_sta = MD5_A0; - ctxt->md5_stb = MD5_B0; - ctxt->md5_stc = MD5_C0; - ctxt->md5_std = MD5_D0; - memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); -} - -void -md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len) -{ - unsigned int gap, - i; - - ctxt->md5_n += len * 8; /* byte to bit */ - gap = MD5_BUFLEN - ctxt->md5_i; - - if (len >= gap) - { - memmove(ctxt->md5_buf + ctxt->md5_i, input, gap); - md5_calc(ctxt->md5_buf, ctxt); - - for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) - md5_calc(input + i, ctxt); - - ctxt->md5_i = len - i; - memmove(ctxt->md5_buf, input + i, ctxt->md5_i); - } - else - { - memmove(ctxt->md5_buf + ctxt->md5_i, input, len); - ctxt->md5_i += len; - } -} - -void -md5_pad(md5_ctxt *ctxt) -{ - unsigned int gap; - - /* Don't count up padding. Keep md5_n. */ - gap = MD5_BUFLEN - ctxt->md5_i; - if (gap > 8) - { - memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, - gap - sizeof(ctxt->md5_n)); - } - else - { - /* including gap == 8 */ - memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); - md5_calc(ctxt->md5_buf, ctxt); - memmove(ctxt->md5_buf, md5_paddat + gap, - MD5_BUFLEN - sizeof(ctxt->md5_n)); - } - - /* 8 byte word */ -#ifndef WORDS_BIGENDIAN - memmove(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); -#else - ctxt->md5_buf[56] = ctxt->md5_n8[7]; - ctxt->md5_buf[57] = ctxt->md5_n8[6]; - ctxt->md5_buf[58] = ctxt->md5_n8[5]; - ctxt->md5_buf[59] = ctxt->md5_n8[4]; - ctxt->md5_buf[60] = ctxt->md5_n8[3]; - ctxt->md5_buf[61] = ctxt->md5_n8[2]; - ctxt->md5_buf[62] = ctxt->md5_n8[1]; - ctxt->md5_buf[63] = ctxt->md5_n8[0]; -#endif - - md5_calc(ctxt->md5_buf, ctxt); -} - -void -md5_result(uint8 *digest, md5_ctxt *ctxt) -{ - /* 4 byte words */ -#ifndef WORDS_BIGENDIAN - memmove(digest, &ctxt->md5_st8[0], 16); -#else - digest[0] = ctxt->md5_st8[3]; - digest[1] = ctxt->md5_st8[2]; - digest[2] = ctxt->md5_st8[1]; - digest[3] = ctxt->md5_st8[0]; - digest[4] = ctxt->md5_st8[7]; - digest[5] = ctxt->md5_st8[6]; - digest[6] = ctxt->md5_st8[5]; - digest[7] = ctxt->md5_st8[4]; - digest[8] = ctxt->md5_st8[11]; - digest[9] = ctxt->md5_st8[10]; - digest[10] = ctxt->md5_st8[9]; - digest[11] = ctxt->md5_st8[8]; - digest[12] = ctxt->md5_st8[15]; - digest[13] = ctxt->md5_st8[14]; - digest[14] = ctxt->md5_st8[13]; - digest[15] = ctxt->md5_st8[12]; -#endif -} - -#ifdef WORDS_BIGENDIAN -static uint32 X[16]; -#endif - -static void -md5_calc(const uint8 *b64, md5_ctxt *ctxt) -{ - uint32 A = ctxt->md5_sta; - uint32 B = ctxt->md5_stb; - uint32 C = ctxt->md5_stc; - uint32 D = ctxt->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 - - 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); - - ctxt->md5_sta += A; - ctxt->md5_stb += B; - ctxt->md5_stc += C; - ctxt->md5_std += D; -} diff --git a/contrib/pgcrypto/md5.h b/contrib/pgcrypto/md5.h deleted file mode 100644 index 3e6e8da5e7..0000000000 --- a/contrib/pgcrypto/md5.h +++ /dev/null @@ -1,79 +0,0 @@ -/* contrib/pgcrypto/md5.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 _NETINET6_MD5_H_ -#define _NETINET6_MD5_H_ - -#define MD5_BUFLEN 64 - -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]; -} md5_ctxt; - -extern void md5_init(md5_ctxt *); -extern void md5_loop(md5_ctxt *, const uint8 *, unsigned int); -extern void md5_pad(md5_ctxt *); -extern void md5_result(uint8 *, md5_ctxt *); - -/* compatibility */ -#define MD5_CTX md5_ctxt -#define MD5Init(x) md5_init((x)) -#define MD5Update(x, y, z) md5_loop((x), (y), (z)) -#define MD5Final(x, y) \ -do { \ - md5_pad((y)); \ - md5_result((x), (y)); \ -} while (0) - -#endif /* ! _NETINET6_MD5_H_ */ diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 90594bd41b..055863c9b2 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.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); @@ -463,11 +463,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'); -- 2.29.2
From 677c3d3dcc202593ba76ad180b235cf1217d2594 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Tue, 10 Nov 2020 13:24:15 +0900 Subject: [PATCH v2 3/3] Add MD5 implementation based on OpenSSL This makes use of OpenSSL EVP to compute MD5 hashes, using the new API interface introduced previously. --- src/common/Makefile | 8 +- src/common/md5_openssl.c | 157 ++++++++++++++++++++++++++++++++++++ src/tools/msvc/Mkvcbuild.pm | 4 +- 3 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 src/common/md5_openssl.c diff --git a/src/common/Makefile b/src/common/Makefile index 69de65fab5..4571a8ac23 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -63,7 +63,6 @@ OBJS_COMMON = \ keywords.o \ kwlookup.o \ link-canary.o \ - md5.o \ md5_common.o \ pg_get_line.o \ pg_lzcompress.o \ @@ -83,9 +82,12 @@ OBJS_COMMON = \ ifeq ($(with_openssl),yes) OBJS_COMMON += \ protocol_openssl.o \ - sha2_openssl.o + sha2_openssl.o \ + md5_openssl.o else -OBJS_COMMON += sha2.o +OBJS_COMMON += \ + md5.o \ + sha2.o endif # A few files are currently only built for frontend, not server diff --git a/src/common/md5_openssl.c b/src/common/md5_openssl.c new file mode 100644 index 0000000000..56bef35ee8 --- /dev/null +++ b/src/common/md5_openssl.c @@ -0,0 +1,157 @@ +/*------------------------------------------------------------------------- + * + * md5_openssl.c + * Set of wrapper routines on top of OpenSSL to support MD5. + * + * This should only be used if code is compiled with OpenSSL support. + * + * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/common/md52_openssl.c + * + *------------------------------------------------------------------------- + */ + +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#include <openssl/evp.h> + +#include "common/md5.h" +#ifndef FRONTEND +#include "utils/memutils.h" +#include "utils/resowner.h" +#include "utils/resowner_private.h" +#endif + +/* + * In backend, use palloc/pfree to ease the error handling. In frontend, + * use malloc to be able to return a failure status back to the caller. + */ +#ifndef FRONTEND +#define ALLOC(size) palloc(size) +#define FREE(ptr) pfree(ptr) +#else +#define ALLOC(size) malloc(size) +#define FREE(ptr) free(ptr) +#endif + +/* + * pg_md5_create + * + * Allocate a MD5 context. Returns NULL on failure. + */ +void * +pg_md5_create(void) +{ + void *ctx; + +#ifndef FRONTEND + ResourceOwnerEnlargeEVP(CurrentResourceOwner); +#endif + + ctx = EVP_MD_CTX_create(); + + if (ctx == NULL) + { +#ifndef FRONTEND + elog(ERROR, "out of memory"); +#else + return NULL; +#endif + } + +#ifndef FRONTEND + ResourceOwnerRememberEVP(CurrentResourceOwner, + PointerGetDatum(ctx)); +#endif + + return ctx; +} + +/* + * pg_md5_init + * + * Initialize a MD5 context. Returns 0 on success, and -1 on failure. + */ +int +pg_md5_init(void *ctx) +{ + int status = 0; + + if (ctx == NULL) + return 0; + + status = EVP_DigestInit_ex((EVP_MD_CTX *) ctx, + EVP_md5(), NULL); + + /* OpenSSL internals return 1 on success, 0 on failure */ + if (status <= 0) + return -1; + return 0; +} + +/* + * pg_md5_update + * + * Update a MD5 context. Returns 0 on success, and -1 on failure. + */ +int +pg_md5_update(void *ctx, const uint8 *data, size_t len) +{ + int status; + + if (ctx == NULL) + return 0; + + status = EVP_DigestUpdate((EVP_MD_CTX *) ctx, data, len); + + /* OpenSSL internals return 1 on success, 0 on failure */ + if (status <= 0) + return -1; + return 0; +} + +/* + * pg_md5_final + * + * Finalize a MD5 context. Returns 0 on success, and -1 on failure. + */ +int +pg_md5_final(void *ctx, uint8 *dest) +{ + int status; + + if (ctx == NULL) + return 0; + + status = EVP_DigestFinal_ex((EVP_MD_CTX *) ctx, dest, 0); + + /* OpenSSL internals return 1 on success, 0 on failure */ + if (status <= 0) + return -1; + return 0; +} + +/* + * pg_md5_free + * + * Free a MD5 context. + */ +void +pg_md5_free(void *ctx) +{ + if (ctx == NULL) + return; + + EVP_MD_CTX_destroy((EVP_MD_CTX *) ctx); + +#ifndef FRONTEND + ResourceOwnerForgetEVP(CurrentResourceOwner, + PointerGetDatum(ctx)); +#endif +} diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 055863c9b2..eb9e401674 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -122,18 +122,20 @@ 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 md5_common.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); if ($solution->{options}->{openssl}) { + push(@pgcommonallfiles, 'md5_openssl.c'); push(@pgcommonallfiles, 'sha2_openssl.c'); push(@pgcommonallfiles, 'protocol_openssl.c'); } else { + push(@pgcommonallfiles, 'md5.c'); push(@pgcommonallfiles, 'sha2.c'); } -- 2.29.2
signature.asc
Description: PGP signature