PostgreSQL Source Code git master
md5.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * md5.c
4 * Implements the MD5 Message-Digest Algorithm
5 *
6 * Fallback implementation of MD5, as specified in RFC 1321. This
7 * implementation is a simple one, in that it needs every input byte
8 * to be buffered before doing any calculations.
9 *
10 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
12 *
13 * IDENTIFICATION
14 * src/common/md5.c
15 *
16 *-------------------------------------------------------------------------
17 */
18
19/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */
20
21/*
22 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
23 * All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 * 3. Neither the name of the project nor the names of its contributors
34 * may be used to endorse or promote products derived from this software
35 * without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 */
49
50#ifndef FRONTEND
51#include "postgres.h"
52#else
53#include "postgres_fe.h"
54#endif
55
56#include "md5_int.h"
57
58#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
59
60#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
61#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
62#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
63#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
64
65#define ROUND1(a, b, c, d, k, s, i) \
66do { \
67 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
68 (a) = SHIFT((a), (s)); \
69 (a) = (b) + (a); \
70} while (0)
71
72#define ROUND2(a, b, c, d, k, s, i) \
73do { \
74 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
75 (a) = SHIFT((a), (s)); \
76 (a) = (b) + (a); \
77} while (0)
78
79#define ROUND3(a, b, c, d, k, s, i) \
80do { \
81 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
82 (a) = SHIFT((a), (s)); \
83 (a) = (b) + (a); \
84} while (0)
85
86#define ROUND4(a, b, c, d, k, s, i) \
87do { \
88 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
89 (a) = SHIFT((a), (s)); \
90 (a) = (b) + (a); \
91} while (0)
92
93#define Sa 7
94#define Sb 12
95#define Sc 17
96#define Sd 22
97
98#define Se 5
99#define Sf 9
100#define Sg 14
101#define Sh 20
102
103#define Si 4
104#define Sj 11
105#define Sk 16
106#define Sl 23
107
108#define Sm 6
109#define Sn 10
110#define So 15
111#define Sp 21
112
113#define MD5_A0 0x67452301
114#define MD5_B0 0xefcdab89
115#define MD5_C0 0x98badcfe
116#define MD5_D0 0x10325476
117
118/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
119static const uint32 T[65] = {
120 0,
121 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
122 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
123 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
124 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
125
126 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
127 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
128 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
129 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
130
131 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
132 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
133 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
134 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
135
136 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
137 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
138 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
139 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
140};
141
142static const uint8 md5_paddat[MD5_BUFLEN] = {
143 0x80, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0,
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0,
151};
152
153static void
154md5_calc(const uint8 *b64, pg_md5_ctx *ctx)
155{
156 uint32 A = ctx->md5_sta;
157 uint32 B = ctx->md5_stb;
158 uint32 C = ctx->md5_stc;
159 uint32 D = ctx->md5_std;
160
161#ifndef WORDS_BIGENDIAN
162 const uint32 *X = (const uint32 *) b64;
163#else
164 /* 4 byte words */
165 /* what a brute force but fast! */
166 uint32 X[16];
167 uint8 *y = (uint8 *) X;
168
169 y[0] = b64[3];
170 y[1] = b64[2];
171 y[2] = b64[1];
172 y[3] = b64[0];
173 y[4] = b64[7];
174 y[5] = b64[6];
175 y[6] = b64[5];
176 y[7] = b64[4];
177 y[8] = b64[11];
178 y[9] = b64[10];
179 y[10] = b64[9];
180 y[11] = b64[8];
181 y[12] = b64[15];
182 y[13] = b64[14];
183 y[14] = b64[13];
184 y[15] = b64[12];
185 y[16] = b64[19];
186 y[17] = b64[18];
187 y[18] = b64[17];
188 y[19] = b64[16];
189 y[20] = b64[23];
190 y[21] = b64[22];
191 y[22] = b64[21];
192 y[23] = b64[20];
193 y[24] = b64[27];
194 y[25] = b64[26];
195 y[26] = b64[25];
196 y[27] = b64[24];
197 y[28] = b64[31];
198 y[29] = b64[30];
199 y[30] = b64[29];
200 y[31] = b64[28];
201 y[32] = b64[35];
202 y[33] = b64[34];
203 y[34] = b64[33];
204 y[35] = b64[32];
205 y[36] = b64[39];
206 y[37] = b64[38];
207 y[38] = b64[37];
208 y[39] = b64[36];
209 y[40] = b64[43];
210 y[41] = b64[42];
211 y[42] = b64[41];
212 y[43] = b64[40];
213 y[44] = b64[47];
214 y[45] = b64[46];
215 y[46] = b64[45];
216 y[47] = b64[44];
217 y[48] = b64[51];
218 y[49] = b64[50];
219 y[50] = b64[49];
220 y[51] = b64[48];
221 y[52] = b64[55];
222 y[53] = b64[54];
223 y[54] = b64[53];
224 y[55] = b64[52];
225 y[56] = b64[59];
226 y[57] = b64[58];
227 y[58] = b64[57];
228 y[59] = b64[56];
229 y[60] = b64[63];
230 y[61] = b64[62];
231 y[62] = b64[61];
232 y[63] = b64[60];
233#endif
234
235 ROUND1(A, B, C, D, 0, Sa, 1);
236 ROUND1(D, A, B, C, 1, Sb, 2);
237 ROUND1(C, D, A, B, 2, Sc, 3);
238 ROUND1(B, C, D, A, 3, Sd, 4);
239 ROUND1(A, B, C, D, 4, Sa, 5);
240 ROUND1(D, A, B, C, 5, Sb, 6);
241 ROUND1(C, D, A, B, 6, Sc, 7);
242 ROUND1(B, C, D, A, 7, Sd, 8);
243 ROUND1(A, B, C, D, 8, Sa, 9);
244 ROUND1(D, A, B, C, 9, Sb, 10);
245 ROUND1(C, D, A, B, 10, Sc, 11);
246 ROUND1(B, C, D, A, 11, Sd, 12);
247 ROUND1(A, B, C, D, 12, Sa, 13);
248 ROUND1(D, A, B, C, 13, Sb, 14);
249 ROUND1(C, D, A, B, 14, Sc, 15);
250 ROUND1(B, C, D, A, 15, Sd, 16);
251
252 ROUND2(A, B, C, D, 1, Se, 17);
253 ROUND2(D, A, B, C, 6, Sf, 18);
254 ROUND2(C, D, A, B, 11, Sg, 19);
255 ROUND2(B, C, D, A, 0, Sh, 20);
256 ROUND2(A, B, C, D, 5, Se, 21);
257 ROUND2(D, A, B, C, 10, Sf, 22);
258 ROUND2(C, D, A, B, 15, Sg, 23);
259 ROUND2(B, C, D, A, 4, Sh, 24);
260 ROUND2(A, B, C, D, 9, Se, 25);
261 ROUND2(D, A, B, C, 14, Sf, 26);
262 ROUND2(C, D, A, B, 3, Sg, 27);
263 ROUND2(B, C, D, A, 8, Sh, 28);
264 ROUND2(A, B, C, D, 13, Se, 29);
265 ROUND2(D, A, B, C, 2, Sf, 30);
266 ROUND2(C, D, A, B, 7, Sg, 31);
267 ROUND2(B, C, D, A, 12, Sh, 32);
268
269 ROUND3(A, B, C, D, 5, Si, 33);
270 ROUND3(D, A, B, C, 8, Sj, 34);
271 ROUND3(C, D, A, B, 11, Sk, 35);
272 ROUND3(B, C, D, A, 14, Sl, 36);
273 ROUND3(A, B, C, D, 1, Si, 37);
274 ROUND3(D, A, B, C, 4, Sj, 38);
275 ROUND3(C, D, A, B, 7, Sk, 39);
276 ROUND3(B, C, D, A, 10, Sl, 40);
277 ROUND3(A, B, C, D, 13, Si, 41);
278 ROUND3(D, A, B, C, 0, Sj, 42);
279 ROUND3(C, D, A, B, 3, Sk, 43);
280 ROUND3(B, C, D, A, 6, Sl, 44);
281 ROUND3(A, B, C, D, 9, Si, 45);
282 ROUND3(D, A, B, C, 12, Sj, 46);
283 ROUND3(C, D, A, B, 15, Sk, 47);
284 ROUND3(B, C, D, A, 2, Sl, 48);
285
286 ROUND4(A, B, C, D, 0, Sm, 49);
287 ROUND4(D, A, B, C, 7, Sn, 50);
288 ROUND4(C, D, A, B, 14, So, 51);
289 ROUND4(B, C, D, A, 5, Sp, 52);
290 ROUND4(A, B, C, D, 12, Sm, 53);
291 ROUND4(D, A, B, C, 3, Sn, 54);
292 ROUND4(C, D, A, B, 10, So, 55);
293 ROUND4(B, C, D, A, 1, Sp, 56);
294 ROUND4(A, B, C, D, 8, Sm, 57);
295 ROUND4(D, A, B, C, 15, Sn, 58);
296 ROUND4(C, D, A, B, 6, So, 59);
297 ROUND4(B, C, D, A, 13, Sp, 60);
298 ROUND4(A, B, C, D, 4, Sm, 61);
299 ROUND4(D, A, B, C, 11, Sn, 62);
300 ROUND4(C, D, A, B, 2, So, 63);
301 ROUND4(B, C, D, A, 9, Sp, 64);
302
303 ctx->md5_sta += A;
304 ctx->md5_stb += B;
305 ctx->md5_stc += C;
306 ctx->md5_std += D;
307}
308
309static void
311{
312 unsigned int gap;
313
314 /* Don't count up padding. Keep md5_n. */
315 gap = MD5_BUFLEN - ctx->md5_i;
316 if (gap > 8)
317 {
318 memmove(ctx->md5_buf + ctx->md5_i, md5_paddat,
319 gap - sizeof(ctx->md5_n));
320 }
321 else
322 {
323 /* including gap == 8 */
324 memmove(ctx->md5_buf + ctx->md5_i, md5_paddat, gap);
325 md5_calc(ctx->md5_buf, ctx);
326 memmove(ctx->md5_buf, md5_paddat + gap,
327 MD5_BUFLEN - sizeof(ctx->md5_n));
328 }
329
330 /* 8 byte word */
331#ifndef WORDS_BIGENDIAN
332 memmove(&ctx->md5_buf[56], &ctx->md5_n8[0], 8);
333#else
334 ctx->md5_buf[56] = ctx->md5_n8[7];
335 ctx->md5_buf[57] = ctx->md5_n8[6];
336 ctx->md5_buf[58] = ctx->md5_n8[5];
337 ctx->md5_buf[59] = ctx->md5_n8[4];
338 ctx->md5_buf[60] = ctx->md5_n8[3];
339 ctx->md5_buf[61] = ctx->md5_n8[2];
340 ctx->md5_buf[62] = ctx->md5_n8[1];
341 ctx->md5_buf[63] = ctx->md5_n8[0];
342#endif
343
344 md5_calc(ctx->md5_buf, ctx);
345}
346
347static void
349{
350 /* 4 byte words */
351#ifndef WORDS_BIGENDIAN
352 memmove(digest, &ctx->md5_st8[0], 16);
353#else
354 digest[0] = ctx->md5_st8[3];
355 digest[1] = ctx->md5_st8[2];
356 digest[2] = ctx->md5_st8[1];
357 digest[3] = ctx->md5_st8[0];
358 digest[4] = ctx->md5_st8[7];
359 digest[5] = ctx->md5_st8[6];
360 digest[6] = ctx->md5_st8[5];
361 digest[7] = ctx->md5_st8[4];
362 digest[8] = ctx->md5_st8[11];
363 digest[9] = ctx->md5_st8[10];
364 digest[10] = ctx->md5_st8[9];
365 digest[11] = ctx->md5_st8[8];
366 digest[12] = ctx->md5_st8[15];
367 digest[13] = ctx->md5_st8[14];
368 digest[14] = ctx->md5_st8[13];
369 digest[15] = ctx->md5_st8[12];
370#endif
371}
372
373
374/* External routines for this MD5 implementation */
375
376/*
377 * pg_md5_init
378 *
379 * Initialize a MD5 context.
380 */
381void
383{
384 ctx->md5_n = 0;
385 ctx->md5_i = 0;
386 ctx->md5_sta = MD5_A0;
387 ctx->md5_stb = MD5_B0;
388 ctx->md5_stc = MD5_C0;
389 ctx->md5_std = MD5_D0;
390 memset(ctx->md5_buf, 0, sizeof(ctx->md5_buf));
391}
392
393
394/*
395 * pg_md5_update
396 *
397 * Update a MD5 context.
398 */
399void
400pg_md5_update(pg_md5_ctx *ctx, const uint8 *data, size_t len)
401{
402 unsigned int gap,
403 i;
404
405 ctx->md5_n += len * 8; /* byte to bit */
406 gap = MD5_BUFLEN - ctx->md5_i;
407
408 if (len >= gap)
409 {
410 memmove(ctx->md5_buf + ctx->md5_i, data, gap);
411 md5_calc(ctx->md5_buf, ctx);
412
413 for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN)
414 md5_calc(data + i, ctx);
415
416 ctx->md5_i = len - i;
417 memmove(ctx->md5_buf, data + i, ctx->md5_i);
418 }
419 else
420 {
421 memmove(ctx->md5_buf + ctx->md5_i, data, len);
422 ctx->md5_i += len;
423 }
424}
425
426/*
427 * pg_md5_final
428 *
429 * Finalize a MD5 context.
430 */
431void
433{
434 md5_pad(ctx);
435 md5_result(dest, ctx);
436}
uint8_t uint8
Definition: c.h:486
uint32_t uint32
Definition: c.h:488
int y
Definition: isn.c:71
int i
Definition: isn.c:72
#define Sj
Definition: md5.c:104
#define Sc
Definition: md5.c:95
#define Sd
Definition: md5.c:96
#define ROUND2(a, b, c, d, k, s, i)
Definition: md5.c:72
static void md5_result(uint8 *digest, pg_md5_ctx *ctx)
Definition: md5.c:348
#define Sn
Definition: md5.c:109
void pg_md5_init(pg_md5_ctx *ctx)
Definition: md5.c:382
#define Sh
Definition: md5.c:101
#define Sa
Definition: md5.c:93
void pg_md5_update(pg_md5_ctx *ctx, const uint8 *data, size_t len)
Definition: md5.c:400
#define MD5_B0
Definition: md5.c:114
#define Se
Definition: md5.c:98
#define ROUND3(a, b, c, d, k, s, i)
Definition: md5.c:79
void pg_md5_final(pg_md5_ctx *ctx, uint8 *dest)
Definition: md5.c:432
#define Sg
Definition: md5.c:100
#define Sk
Definition: md5.c:105
#define Si
Definition: md5.c:103
#define ROUND1(a, b, c, d, k, s, i)
Definition: md5.c:65
#define Sp
Definition: md5.c:111
#define MD5_C0
Definition: md5.c:115
#define Sf
Definition: md5.c:99
static const uint8 md5_paddat[MD5_BUFLEN]
Definition: md5.c:142
#define ROUND4(a, b, c, d, k, s, i)
Definition: md5.c:86
#define MD5_D0
Definition: md5.c:116
static void md5_pad(pg_md5_ctx *ctx)
Definition: md5.c:310
#define Sb
Definition: md5.c:94
#define Sl
Definition: md5.c:106
static const uint32 T[65]
Definition: md5.c:119
#define Sm
Definition: md5.c:108
#define MD5_A0
Definition: md5.c:113
static void md5_calc(const uint8 *b64, pg_md5_ctx *ctx)
Definition: md5.c:154
#define So
Definition: md5.c:110
#define MD5_BUFLEN
Definition: md5_int.h:51
const void size_t len
const void * data
unsigned int md5_i
Definition: md5_int.h:76
uint8 md5_buf[MD5_BUFLEN]
Definition: md5_int.h:77