40#include <winpr/cast.h>
51static inline winpr_MD5_u32plus F(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
53 return ((z) ^ ((x) & ((y) ^ (z))));
55static inline winpr_MD5_u32plus G(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
57 return ((y) ^ ((z) & ((x) ^ (y))));
59static inline winpr_MD5_u32plus H(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
61 return (((x) ^ (y)) ^ (z));
63static inline winpr_MD5_u32plus H2(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
65 return ((x) ^ ((y) ^ (z)));
67static inline winpr_MD5_u32plus I(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
69 return ((y) ^ ((x) | ~(z)));
75#define STEP(f, a, b, c, d, x, t, s) \
76 (a) += f((b), (c), (d)) + (x) + (t); \
77 (a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
96 (ctx->block[(n)] = (winpr_MD5_u32plus)ptr[4ULL * (n)] | \
97 ((winpr_MD5_u32plus)ptr[4ULL * (n) + 1] << 8) | \
98 ((winpr_MD5_u32plus)ptr[4ULL * (n) + 2] << 16) | \
99 ((winpr_MD5_u32plus)ptr[4ULL * (n) + 3] << 24))
100#define GET(n) (ctx->block[(n)])
106static const void* body(
WINPR_MD5_CTX* ctx,
const void* data,
size_t size)
108 const unsigned char* ptr = (
const unsigned char*)data;
110 winpr_MD5_u32plus a = ctx->a;
111 winpr_MD5_u32plus b = ctx->b;
112 winpr_MD5_u32plus c = ctx->c;
113 winpr_MD5_u32plus d = ctx->d;
117 const winpr_MD5_u32plus saved_a = a;
118 const winpr_MD5_u32plus saved_b = b;
119 const winpr_MD5_u32plus saved_c = c;
120 const winpr_MD5_u32plus saved_d = d;
123 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
124 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
125 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
126 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
127 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
128 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
129 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
130 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
131 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
132 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
133 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
134 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
135 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
136 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
137 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
138 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
141 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
142 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
143 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
144 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
145 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
146 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
147 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
148 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
149 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
150 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
151 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
152 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
153 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
154 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
155 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
156 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
159 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
160 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
161 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
162 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
163 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
164 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
165 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
166 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
167 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
168 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
169 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
170 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
171 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
172 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
173 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
174 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
177 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
178 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
179 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
180 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
181 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
182 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
183 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
184 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
185 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
186 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
187 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
188 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
189 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
190 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
191 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
192 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
200 } while (size -= 64);
221void winpr_MD5_Update(
WINPR_MD5_CTX* ctx,
const void* data,
size_t size)
223 winpr_MD5_u32plus saved_lo = ctx->lo;
224 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
226 ctx->hi += (winpr_MD5_u32plus)((size >> 29) & 0xffffffff);
228 size_t used = saved_lo & 0x3f;
232 size_t available = 64 - used;
234 if (size < available)
236 memcpy(&ctx->buffer[used], data, size);
240 memcpy(&ctx->buffer[used], data, available);
241 data = (
const unsigned char*)data + available;
243 body(ctx, ctx->buffer, 64);
248 data = body(ctx, data, size & ~(
size_t)0x3f);
252 memcpy(ctx->buffer, data, size);
255static inline void mdOUT(
unsigned char* dst, winpr_MD5_u32plus src)
257 (dst)[0] = (
unsigned char)(src);
258 (dst)[1] = (
unsigned char)((src) >> 8);
259 (dst)[2] = (
unsigned char)((src) >> 16);
260 (dst)[3] = (
unsigned char)((src) >> 24);
263void winpr_MD5_Final(
unsigned char* result,
WINPR_MD5_CTX* ctx)
265 size_t used = ctx->lo & 0x3f;
267 ctx->buffer[used++] = 0x80;
269 size_t available = 64 - used;
273 memset(&ctx->buffer[used], 0, available);
274 body(ctx, ctx->buffer, 64);
279 memset(&ctx->buffer[used], 0, available - 8);
282 mdOUT(&ctx->buffer[56], ctx->lo);
283 mdOUT(&ctx->buffer[60], ctx->hi);
285 body(ctx, ctx->buffer, 64);
287 mdOUT(&result[0], ctx->a);
288 mdOUT(&result[4], ctx->b);
289 mdOUT(&result[8], ctx->c);
290 mdOUT(&result[12], ctx->d);
292 memset(ctx, 0,
sizeof(*ctx));