-/* $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.
- *
- * $PostgreSQL: pgsql/contrib/pgcrypto/md5.c,v 1.14 2007/04/06 05:36:50 tgl Exp $
+ * MD5 implementation based on RFC1321.
+ *
+ * Copyright (c) 2008 Marko Kreen, Skype Technologies OÜ
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "bouncer.h"
-
+#include "system.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 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_t 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,
-};
+/*
+ * Support functions.
+ */
-static void md5_calc(uint8_t *, md5_ctxt *);
+#define bufpos(ctx) ((ctx)->nbytes & (MD5_BLOCK_LENGTH - 1))
-void
-md5_init(md5_ctxt * ctxt)
+static inline uint32_t rol(uint32_t v, int s)
{
- 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 (v << s) | (v >> (32 - s));
}
-void
-md5_loop(md5_ctxt * ctxt, const uint8_t *input, unsigned len)
+static inline void swap_words(uint32_t *w, int n)
{
- 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((uint8_t *) (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));
+#ifdef WORDS_BIGENDIAN
+ for (; n > 0; w++, n--) {
+ uint32_t v = rol(*w, 16);
+ *w = ((v >> 8) & 0x00FF00FF) | ((v << 8) & 0xFF00FF00);
}
-
- /* 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_t *digest, md5_ctxt * ctxt)
+static inline void put_word(uint8_t *dst, uint32_t val)
{
- /* 4 byte words */
-#ifndef WORDS_BIGENDIAN
- memmove(digest, &ctxt->md5_st8[0], 16);
+#ifdef WORDS_BIGENDIAN
+ dst[0] = val;
+ dst[1] = val >> 8;
+ dst[2] = val >> 16;
+ dst[3] = val >> 24;
#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];
+ memcpy(dst, &val, 4);
#endif
}
-#ifdef WORDS_BIGENDIAN
-static uint32_t X[16];
-#endif
-
-static void
-md5_calc(uint8_t *b64, md5_ctxt * ctxt)
-{
- uint32_t A = ctxt->md5_sta;
- uint32_t B = ctxt->md5_stb;
- uint32_t C = ctxt->md5_stc;
- uint32_t D = ctxt->md5_std;
+/*
+ * MD5 core.
+ */
-#ifndef WORDS_BIGENDIAN
- uint32_t *X = (uint32_t *) b64;
-#else
- /* 4 byte words */
- /* what a brute force but fast! */
- uint8_t *y = (uint8_t *) X;
+#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)))
- 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
+#define OP(fn, a, b, c, d, k, s, T_i) \
+ a = b + rol(a + fn(b, c, d) + X[k] + T_i, s)
- 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);
+static void md5_mix(struct md5_ctx *ctx, const uint32_t *X)
+{
+ uint32_t a, b, c, d;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ /* Round 1. */
+ OP(F, a, b, c, d, 0, 7, 0xd76aa478);
+ OP(F, d, a, b, c, 1, 12, 0xe8c7b756);
+ OP(F, c, d, a, b, 2, 17, 0x242070db);
+ OP(F, b, c, d, a, 3, 22, 0xc1bdceee);
+ OP(F, a, b, c, d, 4, 7, 0xf57c0faf);
+ OP(F, d, a, b, c, 5, 12, 0x4787c62a);
+ OP(F, c, d, a, b, 6, 17, 0xa8304613);
+ OP(F, b, c, d, a, 7, 22, 0xfd469501);
+ OP(F, a, b, c, d, 8, 7, 0x698098d8);
+ OP(F, d, a, b, c, 9, 12, 0x8b44f7af);
+ OP(F, c, d, a, b, 10, 17, 0xffff5bb1);
+ OP(F, b, c, d, a, 11, 22, 0x895cd7be);
+ OP(F, a, b, c, d, 12, 7, 0x6b901122);
+ OP(F, d, a, b, c, 13, 12, 0xfd987193);
+ OP(F, c, d, a, b, 14, 17, 0xa679438e);
+ OP(F, b, c, d, a, 15, 22, 0x49b40821);
+
+ /* Round 2. */
+ OP(G, a, b, c, d, 1, 5, 0xf61e2562);
+ OP(G, d, a, b, c, 6, 9, 0xc040b340);
+ OP(G, c, d, a, b, 11, 14, 0x265e5a51);
+ OP(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
+ OP(G, a, b, c, d, 5, 5, 0xd62f105d);
+ OP(G, d, a, b, c, 10, 9, 0x02441453);
+ OP(G, c, d, a, b, 15, 14, 0xd8a1e681);
+ OP(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
+ OP(G, a, b, c, d, 9, 5, 0x21e1cde6);
+ OP(G, d, a, b, c, 14, 9, 0xc33707d6);
+ OP(G, c, d, a, b, 3, 14, 0xf4d50d87);
+ OP(G, b, c, d, a, 8, 20, 0x455a14ed);
+ OP(G, a, b, c, d, 13, 5, 0xa9e3e905);
+ OP(G, d, a, b, c, 2, 9, 0xfcefa3f8);
+ OP(G, c, d, a, b, 7, 14, 0x676f02d9);
+ OP(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
+
+ /* Round 3. */
+ OP(H, a, b, c, d, 5, 4, 0xfffa3942);
+ OP(H, d, a, b, c, 8, 11, 0x8771f681);
+ OP(H, c, d, a, b, 11, 16, 0x6d9d6122);
+ OP(H, b, c, d, a, 14, 23, 0xfde5380c);
+ OP(H, a, b, c, d, 1, 4, 0xa4beea44);
+ OP(H, d, a, b, c, 4, 11, 0x4bdecfa9);
+ OP(H, c, d, a, b, 7, 16, 0xf6bb4b60);
+ OP(H, b, c, d, a, 10, 23, 0xbebfbc70);
+ OP(H, a, b, c, d, 13, 4, 0x289b7ec6);
+ OP(H, d, a, b, c, 0, 11, 0xeaa127fa);
+ OP(H, c, d, a, b, 3, 16, 0xd4ef3085);
+ OP(H, b, c, d, a, 6, 23, 0x04881d05);
+ OP(H, a, b, c, d, 9, 4, 0xd9d4d039);
+ OP(H, d, a, b, c, 12, 11, 0xe6db99e5);
+ OP(H, c, d, a, b, 15, 16, 0x1fa27cf8);
+ OP(H, b, c, d, a, 2, 23, 0xc4ac5665);
+
+ /* Round 4. */
+ OP(I, a, b, c, d, 0, 6, 0xf4292244);
+ OP(I, d, a, b, c, 7, 10, 0x432aff97);
+ OP(I, c, d, a, b, 14, 15, 0xab9423a7);
+ OP(I, b, c, d, a, 5, 21, 0xfc93a039);
+ OP(I, a, b, c, d, 12, 6, 0x655b59c3);
+ OP(I, d, a, b, c, 3, 10, 0x8f0ccc92);
+ OP(I, c, d, a, b, 10, 15, 0xffeff47d);
+ OP(I, b, c, d, a, 1, 21, 0x85845dd1);
+ OP(I, a, b, c, d, 8, 6, 0x6fa87e4f);
+ OP(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
+ OP(I, c, d, a, b, 6, 15, 0xa3014314);
+ OP(I, b, c, d, a, 13, 21, 0x4e0811a1);
+ OP(I, a, b, c, d, 4, 6, 0xf7537e82);
+ OP(I, d, a, b, c, 11, 10, 0xbd3af235);
+ OP(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
+ OP(I, b, c, d, a, 9, 21, 0xeb86d391);
+
+ ctx->a += a;
+ ctx->b += b;
+ ctx->c += c;
+ ctx->d += d;
+}
- 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);
+/*
+ * Public API.
+ */
- 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);
+void md5_reset(struct md5_ctx *ctx)
+{
+ ctx->nbytes = 0;
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+}
- 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);
+void md5_update(struct md5_ctx *ctx, const void *data, unsigned int len)
+{
+ unsigned int n;
+ const uint8_t *ptr = data;
+ uint8_t *buf = (uint8_t *)ctx->buf;
+
+ while (len > 0) {
+ n = MD5_BLOCK_LENGTH - bufpos(ctx);
+ if (n > len)
+ n = len;
+ memcpy(buf + bufpos(ctx), ptr, n);
+ ptr += n;
+ len -= n;
+ ctx->nbytes += n;
+ if (bufpos(ctx) == 0) {
+ swap_words(ctx->buf, 16);
+ md5_mix(ctx, ctx->buf);
+ }
+ }
+}
- ctxt->md5_sta += A;
- ctxt->md5_stb += B;
- ctxt->md5_stc += C;
- ctxt->md5_std += D;
+void md5_final(uint8_t *dst, struct md5_ctx *ctx)
+{
+ static const uint8_t padding[MD5_BLOCK_LENGTH] = { 0x80 };
+ uint64_t final_len = ctx->nbytes * 8;
+ int pad_len, pos = bufpos(ctx);
+
+ /* add padding */
+ pad_len = MD5_BLOCK_LENGTH - 8 - pos;
+ if (pad_len <= 0)
+ pad_len += MD5_BLOCK_LENGTH;
+ md5_update(ctx, padding, pad_len);
+
+ /* add length directly */
+ swap_words(ctx->buf, 14);
+ ctx->buf[14] = final_len;
+ ctx->buf[15] = final_len >> 32;
+
+ /* final result */
+ md5_mix(ctx, ctx->buf);
+ put_word(dst, ctx->a);
+ put_word(dst + 4, ctx->b);
+ put_word(dst + 8, ctx->c);
+ put_word(dst + 12, ctx->d);
}
-/* vi: set ts=4: */