1a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*
2a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
3a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * MD5 Message-Digest Algorithm (RFC 1321).
4a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
5a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Homepage:
6a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
8a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Author:
9a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
10a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
11a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * This software was written by Alexander Peslyak in 2001.  No copyright is
12a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * claimed, and the software is hereby placed in the public domain.
13a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * In case this attempt to disclaim copyright and place the software in the
14a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * public domain is deemed null and void, then the software is
15a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
16a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * general public under the following terms:
17a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
18a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Redistribution and use in source and binary forms, with or without
19a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * modification, are permitted.
20a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
21a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * There's ABSOLUTELY NO WARRANTY, express or implied.
22a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
23a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * (This is a heavily cut-down "BSD license".)
24a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
25a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * This differs from Colin Plumb's older public domain implementation in that
26a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * no exactly 32-bit integer data type is required (any 32-bit or wider
27a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * unsigned integer data type will do), there's no compile-time endianness
28a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * configuration, and the function prototypes match OpenSSL's.  No code from
29a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * Colin Plumb's implementation has been reused; this comment merely compares
30a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * the properties of the two independent implementations.
31a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
32a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * The primary goals of this implementation are portability and ease of use.
33a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * It is meant to be fast, but not as fast as possible.  Some known
34a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * optimizations are not included to reduce source code size and avoid
35a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * compile-time configuration.
36a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang */
37a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
38a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifndef HAVE_OPENSSL
39a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
40a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include <string.h>
41a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
42a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "md5.h"
43a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
44a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*
45a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * The basic MD5 functions.
46a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
47a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * F and G are optimized compared to their RFC 1321 definitions for
48a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
49a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * implementation.
50a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang */
51a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
52a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
53a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define H(x, y, z)			((x) ^ (y) ^ (z))
54a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define I(x, y, z)			((y) ^ ((x) | ~(z)))
55a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
56a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*
57a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * The MD5 transformation for all four rounds.
58a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang */
59a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define STEP(f, a, b, c, d, x, t, s) \
60a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(a) += f((b), (c), (d)) + (x) + (t); \
61a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
62a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(a) += (b);
63a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
64a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*
65a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * SET reads 4 input bytes in little-endian byte order and stores them
66a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * in a properly aligned word in host byte order.
67a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *
68a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * The check for little-endian architectures that tolerate unaligned
69a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * memory accesses is just an optimization.  Nothing will break if it
70a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * doesn't work.
71a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang */
72a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
73a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define SET(n) \
74a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(*(MD5_u32plus *)&ptr[(n) * 4])
75a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define GET(n) \
76a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	SET(n)
77a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#else
78a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define SET(n) \
79a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(ctx->block[(n)] = \
80a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(MD5_u32plus)ptr[(n) * 4] | \
81a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
82a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
83a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
84a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define GET(n) \
85a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	(ctx->block[(n)])
86a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
87a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
88a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*
89a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * This processes one or more 64-byte data blocks, but does NOT update
90a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang * the bit counters.  There are no alignment requirements.
91a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang */
92a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangstatic void *body(MD5_CTX *ctx, void *data, unsigned long size)
93a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang{
94a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	unsigned char *ptr;
95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	MD5_u32plus a, b, c, d;
96a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	MD5_u32plus saved_a, saved_b, saved_c, saved_d;
97a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
98a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ptr = (unsigned char *)data;
99a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	a = ctx->a;
101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	b = ctx->b;
102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	c = ctx->c;
103a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	d = ctx->d;
104a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	do {
106a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		saved_a = a;
107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		saved_b = b;
108a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		saved_c = c;
109a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		saved_d = d;
110a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
111a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Round 1 */
112a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
114a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
115a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
116a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
117a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
118a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
119a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
121a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
122a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
123a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
124a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
126a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Round 2 */
130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
132a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
134a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
136a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
137a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
138a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
139a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
143a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
144a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
145a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
146a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
147a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Round 3 */
148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
150a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
151a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
159a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
160a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
161a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Round 4 */
166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
182a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
183a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		a += saved_a;
184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		b += saved_b;
185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		c += saved_c;
186a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		d += saved_d;
187a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		ptr += 64;
189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	} while (size -= 64);
190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->a = a;
192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->b = b;
193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->c = c;
194a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->d = d;
195a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
196a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	return ptr;
197a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang}
198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangvoid MD5_Init(MD5_CTX *ctx)
200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang{
201a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->a = 0x67452301;
202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->b = 0xefcdab89;
203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->c = 0x98badcfe;
204a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->d = 0x10325476;
205a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
206a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->lo = 0;
207a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->hi = 0;
208a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang}
209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
210a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangvoid MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
211a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang{
212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	MD5_u32plus saved_lo;
213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	unsigned long used, free;
214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	saved_lo = ctx->lo;
216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		ctx->hi++;
218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->hi += size >> 29;
219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	used = saved_lo & 0x3f;
221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	if (used) {
223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		free = 64 - used;
224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		if (size < free) {
226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang			memcpy(&ctx->buffer[used], data, size);
227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang			return;
228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		}
229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		memcpy(&ctx->buffer[used], data, free);
231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		data = (unsigned char *)data + free;
232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		size -= free;
233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		body(ctx, ctx->buffer, 64);
234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	}
235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	if (size >= 64) {
237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		data = body(ctx, data, size & ~(unsigned long)0x3f);
238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		size &= 0x3f;
239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	}
240a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	memcpy(ctx->buffer, data, size);
242a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang}
243a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangvoid MD5_Final(unsigned char *result, MD5_CTX *ctx)
245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang{
246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	unsigned long used, free;
247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	used = ctx->lo & 0x3f;
249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[used++] = 0x80;
251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	free = 64 - used;
253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	if (free < 8) {
255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		memset(&ctx->buffer[used], 0, free);
256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		body(ctx, ctx->buffer, 64);
257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		used = 0;
258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang		free = 64;
259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	}
260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	memset(&ctx->buffer[used], 0, free - 8);
262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->lo <<= 3;
264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[56] = ctx->lo;
265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[57] = ctx->lo >> 8;
266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[58] = ctx->lo >> 16;
267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[59] = ctx->lo >> 24;
268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[60] = ctx->hi;
269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[61] = ctx->hi >> 8;
270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[62] = ctx->hi >> 16;
271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	ctx->buffer[63] = ctx->hi >> 24;
272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	body(ctx, ctx->buffer, 64);
274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[0] = ctx->a;
276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[1] = ctx->a >> 8;
277a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[2] = ctx->a >> 16;
278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[3] = ctx->a >> 24;
279a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[4] = ctx->b;
280a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[5] = ctx->b >> 8;
281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[6] = ctx->b >> 16;
282a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[7] = ctx->b >> 24;
283a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[8] = ctx->c;
284a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[9] = ctx->c >> 8;
285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[10] = ctx->c >> 16;
286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[11] = ctx->c >> 24;
287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[12] = ctx->d;
288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[13] = ctx->d >> 8;
289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[14] = ctx->d >> 16;
290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	result[15] = ctx->d >> 24;
291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang	memset(ctx, 0, sizeof(*ctx));
293a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang}
294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
296