aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile3
-rw-r--r--src/common/cryptohash.c13
-rw-r--r--src/common/cryptohash_openssl.c3
-rw-r--r--src/common/md5.c683
-rw-r--r--src/common/md5_common.c149
-rw-r--r--src/common/md5_int.h85
-rw-r--r--src/include/common/cryptohash.h3
-rw-r--r--src/include/common/md5.h5
-rw-r--r--src/tools/msvc/Mkvcbuild.pm12
-rw-r--r--src/tools/pgindent/typedefs.list1
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