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