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))));
86 (ctx->block[(n)] = (winpr_MD4_u32plus)ptr[4ULL * (n)] | \
87 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 1] << 8) | \
88 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 2] << 16) | \
89 ((winpr_MD4_u32plus)ptr[4ULL * (n) + 3] << 24))
90#define GET(n) (ctx->block[(n)])
96static const void* body(
WINPR_MD4_CTX* ctx,
const void* data,
size_t size)
98 const winpr_MD4_u32plus ac1 = 0x5a827999;
99 const winpr_MD4_u32plus ac2 = 0x6ed9eba1;
101 const unsigned char* ptr = (
const unsigned char*)data;
103 winpr_MD4_u32plus a = ctx->a;
104 winpr_MD4_u32plus b = ctx->b;
105 winpr_MD4_u32plus c = ctx->c;
106 winpr_MD4_u32plus d = ctx->d;
110 const winpr_MD4_u32plus saved_a = a;
111 const winpr_MD4_u32plus saved_b = b;
112 const winpr_MD4_u32plus saved_c = c;
113 const winpr_MD4_u32plus saved_d = d;
116 STEP(F, a, b, c, d, SET(0), 3)
117 STEP(F, d, a, b, c, SET(1), 7)
118 STEP(F, c, d, a, b, SET(2), 11)
119 STEP(F, b, c, d, a, SET(3), 19)
120 STEP(F, a, b, c, d, SET(4), 3)
121 STEP(F, d, a, b, c, SET(5), 7)
122 STEP(F, c, d, a, b, SET(6), 11)
123 STEP(F, b, c, d, a, SET(7), 19)
124 STEP(F, a, b, c, d, SET(8), 3)
125 STEP(F, d, a, b, c, SET(9), 7)
126 STEP(F, c, d, a, b, SET(10), 11)
127 STEP(F, b, c, d, a, SET(11), 19)
128 STEP(F, a, b, c, d, SET(12), 3)
129 STEP(F, d, a, b, c, SET(13), 7)
130 STEP(F, c, d, a, b, SET(14), 11)
131 STEP(F, b, c, d, a, SET(15), 19)
134 STEP(G, a, b, c, d, GET(0) + ac1, 3)
135 STEP(G, d, a, b, c, GET(4) + ac1, 5)
136 STEP(G, c, d, a, b, GET(8) + ac1, 9)
137 STEP(G, b, c, d, a, GET(12) + ac1, 13)
138 STEP(G, a, b, c, d, GET(1) + ac1, 3)
139 STEP(G, d, a, b, c, GET(5) + ac1, 5)
140 STEP(G, c, d, a, b, GET(9) + ac1, 9)
141 STEP(G, b, c, d, a, GET(13) + ac1, 13)
142 STEP(G, a, b, c, d, GET(2) + ac1, 3)
143 STEP(G, d, a, b, c, GET(6) + ac1, 5)
144 STEP(G, c, d, a, b, GET(10) + ac1, 9)
145 STEP(G, b, c, d, a, GET(14) + ac1, 13)
146 STEP(G, a, b, c, d, GET(3) + ac1, 3)
147 STEP(G, d, a, b, c, GET(7) + ac1, 5)
148 STEP(G, c, d, a, b, GET(11) + ac1, 9)
149 STEP(G, b, c, d, a, GET(15) + ac1, 13)
152 STEP(H, a, b, c, d, GET(0) + ac2, 3)
153 STEP(H, d, a, b, c, GET(8) + ac2, 9)
154 STEP(H, c, d, a, b, GET(4) + ac2, 11)
155 STEP(H, b, c, d, a, GET(12) + ac2, 15)
156 STEP(H, a, b, c, d, GET(2) + ac2, 3)
157 STEP(H, d, a, b, c, GET(10) + ac2, 9)
158 STEP(H, c, d, a, b, GET(6) + ac2, 11)
159 STEP(H, b, c, d, a, GET(14) + ac2, 15)
160 STEP(H, a, b, c, d, GET(1) + ac2, 3)
161 STEP(H, d, a, b, c, GET(9) + ac2, 9)
162 STEP(H, c, d, a, b, GET(5) + ac2, 11)
163 STEP(H, b, c, d, a, GET(13) + ac2, 15)
164 STEP(H, a, b, c, d, GET(3) + ac2, 3)
165 STEP(H, d, a, b, c, GET(11) + ac2, 9)
166 STEP(H, c, d, a, b, GET(7) + ac2, 11)
167 STEP(H, b, c, d, a, GET(15) + ac2, 15)
175 } while (size -= 64);
196void winpr_MD4_Update(
WINPR_MD4_CTX* ctx,
const void* data,
size_t size)
198 winpr_MD4_u32plus saved_lo = ctx->lo;
199 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
201 ctx->hi += (winpr_MD4_u32plus)((size >> 29) & 0xffffffff);
203 size_t used = saved_lo & 0x3f;
207 size_t available = 64 - used;
209 if (size < available)
211 memcpy(&ctx->buffer[used], data, size);
215 memcpy(&ctx->buffer[used], data, available);
216 data = (
const unsigned char*)data + available;
218 body(ctx, ctx->buffer, 64);
223 data = body(ctx, data, size & ~(
size_t)0x3f);
227 memcpy(ctx->buffer, data, size);
230static inline void mdOUT(
unsigned char* dst, winpr_MD4_u32plus src)
232 (dst)[0] = (
unsigned char)(src);
233 (dst)[1] = (
unsigned char)((src) >> 8);
234 (dst)[2] = (
unsigned char)((src) >> 16);
235 (dst)[3] = (
unsigned char)((src) >> 24);
238void winpr_MD4_Final(
unsigned char* result,
WINPR_MD4_CTX* ctx)
240 size_t used = ctx->lo & 0x3f;
242 ctx->buffer[used++] = 0x80;
244 size_t available = 64 - used;
248 memset(&ctx->buffer[used], 0, available);
249 body(ctx, ctx->buffer, 64);
254 memset(&ctx->buffer[used], 0, available - 8);
257 mdOUT(&ctx->buffer[56], ctx->lo);
258 mdOUT(&ctx->buffer[60], ctx->hi);
260 body(ctx, ctx->buffer, 64);
262 mdOUT(&result[0], ctx->a);
263 mdOUT(&result[4], ctx->b);
264 mdOUT(&result[8], ctx->c);
265 mdOUT(&result[12], ctx->d);
267 memset(ctx, 0,
sizeof(*ctx));