40#include <winpr/cast.h>
50static inline winpr_MD4_u32plus F(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
52 return ((z) ^ ((x) & ((y) ^ (z))));
54static inline winpr_MD4_u32plus G(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
56 return (((x) & ((y) | (z))) | ((y) & (z)));
58static inline winpr_MD4_u32plus H(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
60 return ((x) ^ (y) ^ (z));
66#define STEP(f, a, b, c, d, x, s) \
67 (a) += f((b), (c), (d)) + (x); \
68 (a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s))));
85#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
86#define SET(n) (*(WINPR_PACKED_ALIGN_CAST(const winpr_MD4_u32plus*, &ptr[4ULL * (n)])))
90 (ctx->block[(n)] = (winpr_MD4_u32plus)ptr[4ULL * (n)] | \
91 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 1] << 8) | \
92 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 2] << 16) | \
93 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 3] << 24))
94#define GET(n) (ctx->block[(n)])
101static const void* body(
WINPR_MD4_CTX* ctx,
const void* data,
size_t size)
103 const winpr_MD4_u32plus ac1 = 0x5a827999;
104 const winpr_MD4_u32plus ac2 = 0x6ed9eba1;
106 const unsigned char* ptr = (
const unsigned char*)data;
108 winpr_MD4_u32plus a = ctx->a;
109 winpr_MD4_u32plus b = ctx->b;
110 winpr_MD4_u32plus c = ctx->c;
111 winpr_MD4_u32plus d = ctx->d;
115 const winpr_MD4_u32plus saved_a = a;
116 const winpr_MD4_u32plus saved_b = b;
117 const winpr_MD4_u32plus saved_c = c;
118 const winpr_MD4_u32plus saved_d = d;
121 STEP(F, a, b, c, d, SET(0), 3)
122 STEP(F, d, a, b, c, SET(1), 7)
123 STEP(F, c, d, a, b, SET(2), 11)
124 STEP(F, b, c, d, a, SET(3), 19)
125 STEP(F, a, b, c, d, SET(4), 3)
126 STEP(F, d, a, b, c, SET(5), 7)
127 STEP(F, c, d, a, b, SET(6), 11)
128 STEP(F, b, c, d, a, SET(7), 19)
129 STEP(F, a, b, c, d, SET(8), 3)
130 STEP(F, d, a, b, c, SET(9), 7)
131 STEP(F, c, d, a, b, SET(10), 11)
132 STEP(F, b, c, d, a, SET(11), 19)
133 STEP(F, a, b, c, d, SET(12), 3)
134 STEP(F, d, a, b, c, SET(13), 7)
135 STEP(F, c, d, a, b, SET(14), 11)
136 STEP(F, b, c, d, a, SET(15), 19)
139 STEP(G, a, b, c, d, GET(0) + ac1, 3)
140 STEP(G, d, a, b, c, GET(4) + ac1, 5)
141 STEP(G, c, d, a, b, GET(8) + ac1, 9)
142 STEP(G, b, c, d, a, GET(12) + ac1, 13)
143 STEP(G, a, b, c, d, GET(1) + ac1, 3)
144 STEP(G, d, a, b, c, GET(5) + ac1, 5)
145 STEP(G, c, d, a, b, GET(9) + ac1, 9)
146 STEP(G, b, c, d, a, GET(13) + ac1, 13)
147 STEP(G, a, b, c, d, GET(2) + ac1, 3)
148 STEP(G, d, a, b, c, GET(6) + ac1, 5)
149 STEP(G, c, d, a, b, GET(10) + ac1, 9)
150 STEP(G, b, c, d, a, GET(14) + ac1, 13)
151 STEP(G, a, b, c, d, GET(3) + ac1, 3)
152 STEP(G, d, a, b, c, GET(7) + ac1, 5)
153 STEP(G, c, d, a, b, GET(11) + ac1, 9)
154 STEP(G, b, c, d, a, GET(15) + ac1, 13)
157 STEP(H, a, b, c, d, GET(0) + ac2, 3)
158 STEP(H, d, a, b, c, GET(8) + ac2, 9)
159 STEP(H, c, d, a, b, GET(4) + ac2, 11)
160 STEP(H, b, c, d, a, GET(12) + ac2, 15)
161 STEP(H, a, b, c, d, GET(2) + ac2, 3)
162 STEP(H, d, a, b, c, GET(10) + ac2, 9)
163 STEP(H, c, d, a, b, GET(6) + ac2, 11)
164 STEP(H, b, c, d, a, GET(14) + ac2, 15)
165 STEP(H, a, b, c, d, GET(1) + ac2, 3)
166 STEP(H, d, a, b, c, GET(9) + ac2, 9)
167 STEP(H, c, d, a, b, GET(5) + ac2, 11)
168 STEP(H, b, c, d, a, GET(13) + ac2, 15)
169 STEP(H, a, b, c, d, GET(3) + ac2, 3)
170 STEP(H, d, a, b, c, GET(11) + ac2, 9)
171 STEP(H, c, d, a, b, GET(7) + ac2, 11)
172 STEP(H, b, c, d, a, GET(15) + ac2, 15)
180 } while (size -= 64);
201void winpr_MD4_Update(
WINPR_MD4_CTX* ctx,
const void* data,
size_t size)
203 winpr_MD4_u32plus saved_lo = ctx->lo;
204 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
206 ctx->hi += (winpr_MD4_u32plus)((size >> 29) & 0xffffffff);
208 size_t used = saved_lo & 0x3f;
212 size_t available = 64 - used;
214 if (size < available)
216 memcpy(&ctx->buffer[used], data, size);
220 memcpy(&ctx->buffer[used], data, available);
221 data = (
const unsigned char*)data + available;
223 body(ctx, ctx->buffer, 64);
228 data = body(ctx, data, size & ~(
size_t)0x3f);
232 memcpy(ctx->buffer, data, size);
235static inline void mdOUT(
unsigned char* dst, winpr_MD4_u32plus src)
237 (dst)[0] = (
unsigned char)(src);
238 (dst)[1] = (
unsigned char)((src) >> 8);
239 (dst)[2] = (
unsigned char)((src) >> 16);
240 (dst)[3] = (
unsigned char)((src) >> 24);
243void winpr_MD4_Final(
unsigned char* result,
WINPR_MD4_CTX* ctx)
245 size_t used = ctx->lo & 0x3f;
247 ctx->buffer[used++] = 0x80;
249 size_t available = 64 - used;
253 memset(&ctx->buffer[used], 0, available);
254 body(ctx, ctx->buffer, 64);
259 memset(&ctx->buffer[used], 0, available - 8);
262 mdOUT(&ctx->buffer[56], ctx->lo);
263 mdOUT(&ctx->buffer[60], ctx->hi);
265 body(ctx, ctx->buffer, 64);
267 mdOUT(&result[0], ctx->a);
268 mdOUT(&result[4], ctx->b);
269 mdOUT(&result[8], ctx->c);
270 mdOUT(&result[12], ctx->d);
272 memset(ctx, 0,
sizeof(*ctx));