1 /*-------------------------------------------------------------------------
4 * Implements the MD5 Message-Digest Algorithm
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.
10 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
16 *-------------------------------------------------------------------------
19 /* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */
22 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
23 * All rights reserved.
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
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.
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
53 #include "postgres_fe.h"
58 #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
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)))
65 #define ROUND1(a, b, c, d, k, s, i) \
67 (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
68 (a) = SHIFT((a), (s)); \
72 #define ROUND2(a, b, c, d, k, s, i) \
74 (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
75 (a) = SHIFT((a), (s)); \
79 #define ROUND3(a, b, c, d, k, s, i) \
81 (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
82 (a) = SHIFT((a), (s)); \
86 #define ROUND4(a, b, c, d, k, s, i) \
88 (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
89 (a) = SHIFT((a), (s)); \
113 #define MD5_A0 0x67452301
114 #define MD5_B0 0xefcdab89
115 #define MD5_C0 0x98badcfe
116 #define MD5_D0 0x10325476
118 /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
119 static const uint32 T
[65] = {
121 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
122 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
123 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
124 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
126 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
127 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
128 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
129 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
131 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
132 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
133 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
134 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
136 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
137 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
138 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
139 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
142 static 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,
154 md5_calc(const uint8
*b64
, pg_md5_ctx
*ctx
)
156 uint32 A
= ctx
->md5_sta
;
157 uint32 B
= ctx
->md5_stb
;
158 uint32 C
= ctx
->md5_stc
;
159 uint32 D
= ctx
->md5_std
;
161 #ifndef WORDS_BIGENDIAN
162 const uint32
*X
= (const uint32
*) b64
;
165 /* what a brute force but fast! */
167 uint8
*y
= (uint8
*) X
;
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);
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);
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);
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);
310 md5_pad(pg_md5_ctx
*ctx
)
314 /* Don't count up padding. Keep md5_n. */
315 gap
= MD5_BUFLEN
- ctx
->md5_i
;
318 memmove(ctx
->md5_buf
+ ctx
->md5_i
, md5_paddat
,
319 gap
- sizeof(ctx
->md5_n
));
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
));
331 #ifndef WORDS_BIGENDIAN
332 memmove(&ctx
->md5_buf
[56], &ctx
->md5_n8
[0], 8);
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];
344 md5_calc(ctx
->md5_buf
, ctx
);
348 md5_result(uint8
*digest
, pg_md5_ctx
*ctx
)
351 #ifndef WORDS_BIGENDIAN
352 memmove(digest
, &ctx
->md5_st8
[0], 16);
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];
374 /* External routines for this MD5 implementation */
379 * Initialize a MD5 context.
382 pg_md5_init(pg_md5_ctx
*ctx
)
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
));
397 * Update a MD5 context.
400 pg_md5_update(pg_md5_ctx
*ctx
, const uint8
*data
, size_t len
)
405 ctx
->md5_n
+= len
* 8; /* byte to bit */
406 gap
= MD5_BUFLEN
- ctx
->md5_i
;
410 memmove(ctx
->md5_buf
+ ctx
->md5_i
, data
, gap
);
411 md5_calc(ctx
->md5_buf
, ctx
);
413 for (i
= gap
; i
+ MD5_BUFLEN
<= len
; i
+= MD5_BUFLEN
)
414 md5_calc(data
+ i
, ctx
);
416 ctx
->md5_i
= len
- i
;
417 memmove(ctx
->md5_buf
, data
+ i
, ctx
->md5_i
);
421 memmove(ctx
->md5_buf
+ ctx
->md5_i
, data
, len
);
429 * Finalize a MD5 context.
432 pg_md5_final(pg_md5_ctx
*ctx
, uint8
*dest
)
435 md5_result(dest
, ctx
);