+++ /dev/null
-/* $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;
-}
-/*
- * 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
*
+ * 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
#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.
- *
+ * 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
- * 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);
}