libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/*
2 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
3 * MD5 Message-Digest Algorithm (RFC 1321).
4 *
5 * Homepage:
6 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
7 *
8 * Author:
9 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
10 *
11 * This software was written by Alexander Peslyak in 2001. No copyright is
12 * claimed, and the software is hereby placed in the public domain.
13 * In case this attempt to disclaim copyright and place the software in the
14 * public domain is deemed null and void, then the software is
15 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
16 * general public under the following terms:
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted.
20 *
21 * There's ABSOLUTELY NO WARRANTY, express or implied.
22 *
23 * (This is a heavily cut-down "BSD license".)
24 *
25 * This differs from Colin Plumb's older public domain implementation in that
26 * no exactly 32-bit integer data type is required (any 32-bit or wider
27 * unsigned integer data type will do), there's no compile-time endianness
28 * configuration, and the function prototypes match OpenSSL's. No code from
29 * Colin Plumb's implementation has been reused; this comment merely compares
30 * the properties of the two independent implementations.
31 *
32 * The primary goals of this implementation are portability and ease of use.
33 * It is meant to be fast, but not as fast as possible. Some known
34 * optimizations are not included to reduce source code size and avoid
35 * compile-time configuration.
36 */
37
38#include <stdbool.h>
39#include <stdio.h>
40#include <string.h>
41
42/* Performance helper macros */
43#ifndef AARU_RESTRICT
44#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
45#define AARU_RESTRICT restrict
46#elif defined(_MSC_VER)
47#define AARU_RESTRICT __restrict
48#else
49#define AARU_RESTRICT
50#endif
51#endif
52#ifndef LIKELY
53#if defined(__GNUC__) || defined(__clang__)
54#define LIKELY(x) __builtin_expect(!!(x), 1)
55#define UNLIKELY(x) __builtin_expect(!!(x), 0)
56#else
57#define LIKELY(x) (x)
58#define UNLIKELY(x) (x)
59#endif
60#endif
61#ifndef HOT
62#if defined(__GNUC__) || defined(__clang__)
63#define HOT __attribute__((hot))
64#else
65#define HOT
66#endif
67#endif
68#ifndef MD5_MAX_UNROLL
69#define MD5_MAX_UNROLL 4
70#endif
71#ifndef MD5_PREFETCH_DISTANCE_BLOCKS
72#define MD5_PREFETCH_DISTANCE_BLOCKS 8
73#endif
74#ifndef MD5_ENABLE_PREFETCH
75#define MD5_ENABLE_PREFETCH 1
76#endif
77#ifndef AARU_PREFETCH
78#if defined(_MSC_VER) && (defined(__SSE2__) || defined(__AVX2__) || defined(__SSSE3__) || defined(__SSE4_1__) || \
79 defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86))
80#define AARU_PREFETCH(addr) _mm_prefetch((const char *)(addr), _MM_HINT_T0)
81#elif defined(__GNUC__) || defined(__clang__)
82#define AARU_PREFETCH(addr) __builtin_prefetch((addr), 0, 3)
83#else
84#define AARU_PREFETCH(addr) ((void)0)
85#endif
86#endif
87#ifndef MD5_UNROLL8_THRESHOLD
88#define MD5_UNROLL8_THRESHOLD 8192UL
89#endif
90#ifndef MD5_UNROLL4_THRESHOLD
91#define MD5_UNROLL4_THRESHOLD 2048UL
92#endif
93#ifndef MD5_UNROLL2_THRESHOLD
94#define MD5_UNROLL2_THRESHOLD 512UL
95#endif
96
97#include "decls.h"
98#include "md5.h"
99
100#if defined(__ARM_NEON) || defined(__ARM_NEON__)
101#include <arm_neon.h>
102#endif
103#if defined(__SSE2__) || defined(__AVX2__) || defined(__SSSE3__) || defined(__SSE4_1__) || defined(__x86_64__) || \
104 defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
105#include <immintrin.h>
106#endif
107
108/*
109 * The basic MD5 functions.
110 *
111 * F and G are optimized compared to their RFC 1321 definitions for
112 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
113 * implementation.
114 */
115#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
116#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
117#define H(x, y, z) (((x) ^ (y)) ^ (z))
118#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
119#define I(x, y, z) ((y) ^ ((x) | ~(z)))
120
121/* Rotate-left helper using compiler intrinsics when available */
122#if defined(_MSC_VER)
123#define ROTL32(x, s) _rotl((x), (s))
124#else
125#if defined(__has_builtin)
126#if __has_builtin(__builtin_rotateleft32)
127#define ROTL32(x, s) __builtin_rotateleft32((x), (s))
128#endif
129#endif
130#endif
131#ifndef ROTL32
132#define ROTL32(x, s) (((uint32_t)(x) << (s)) | ((uint32_t)(x) >> (32 - (s))))
133#endif
134
135/*
136 * The MD5 transformation for all four rounds.
137 */
138#define STEP(f, a, b, c, d, x, t, s) \
139 (a) += f((b), (c), (d)) + (x) + (uint32_t)(t); \
140 (a) = ROTL32((a), (s)); \
141 (a) += (b);
142
143/*
144 * SET reads 4 input bytes in little-endian byte order and stores them in a
145 * properly aligned word in host byte order.
146 *
147 * The check for little-endian architectures that tolerate unaligned memory
148 * accesses is just an optimization. Nothing will break if it fails to detect
149 * a suitable architecture.
150 *
151 * Unfortunately, this optimization may be a C strict aliasing rules violation
152 * if the caller's data buffer has effective type that cannot be aliased by
153 * uint32_t. In practice, this problem may occur if these MD5 routines are
154 * inlined into a calling function, or with future and dangerously advanced
155 * link-time optimizations. For the time being, keeping these MD5 routines in
156 * their own translation unit avoids the problem.
157 */
158#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
159#define SET(n) (*(uint32_t *)&ptr[(n) * 4])
160#define GET(n) SET(n)
161#else
162#define SET(n) \
163 (ctx->block[(n)] = (uint32_t)ptr[(n) * 4] | ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
164 ((uint32_t)ptr[(n) * 4 + 2] << 16) | ((uint32_t)ptr[(n) * 4 + 3] << 24))
165#define GET(n) (ctx->block[(n)])
166#endif
167
168/*
169 * This processes one or more 64-byte data blocks, but does NOT update the bit
170 * counters. There are no alignment requirements.
171 */
172FORCE_INLINE HOT void md5_process_block_loaded(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
173 const unsigned char *AARU_RESTRICT ptr)
174{
175 const uint32_t *wp = (const uint32_t *)ptr; // unaligned ok on supported arch (we gate optimized path)
176 uint32_t A = *a, B = *b, C = *c, D = *d;
177 uint32_t w0 = wp[0];
178 uint32_t w1 = wp[1];
179 uint32_t w2 = wp[2];
180 uint32_t w3 = wp[3];
181 uint32_t w4 = wp[4];
182 uint32_t w5 = wp[5];
183 uint32_t w6 = wp[6];
184 uint32_t w7 = wp[7];
185 uint32_t w8 = wp[8];
186 uint32_t w9 = wp[9];
187 uint32_t w10 = wp[10];
188 uint32_t w11 = wp[11];
189 uint32_t w12 = wp[12];
190 uint32_t w13 = wp[13];
191 uint32_t w14 = wp[14];
192 uint32_t w15 = wp[15];
193
194 uint32_t sA = A, sB = B, sC = C, sD = D;
195
196 /* Round 1 */
197 STEP(F, A, B, C, D, w0, 0xd76aa478, 7)
198 STEP(F, D, A, B, C, w1, 0xe8c7b756, 12)
199 STEP(F, C, D, A, B, w2, 0x242070db, 17)
200 STEP(F, B, C, D, A, w3, 0xc1bdceee, 22)
201 STEP(F, A, B, C, D, w4, 0xf57c0faf, 7)
202 STEP(F, D, A, B, C, w5, 0x4787c62a, 12)
203 STEP(F, C, D, A, B, w6, 0xa8304613, 17)
204 STEP(F, B, C, D, A, w7, 0xfd469501, 22)
205 STEP(F, A, B, C, D, w8, 0x698098d8, 7)
206 STEP(F, D, A, B, C, w9, 0x8b44f7af, 12)
207 STEP(F, C, D, A, B, w10, 0xffff5bb1, 17)
208 STEP(F, B, C, D, A, w11, 0x895cd7be, 22)
209 STEP(F, A, B, C, D, w12, 0x6b901122, 7)
210 STEP(F, D, A, B, C, w13, 0xfd987193, 12)
211 STEP(F, C, D, A, B, w14, 0xa679438e, 17)
212 STEP(F, B, C, D, A, w15, 0x49b40821, 22)
213
214 /* Round 2 */
215 STEP(G, A, B, C, D, w1, 0xf61e2562, 5)
216 STEP(G, D, A, B, C, w6, 0xc040b340, 9)
217 STEP(G, C, D, A, B, w11, 0x265e5a51, 14)
218 STEP(G, B, C, D, A, w0, 0xe9b6c7aa, 20)
219 STEP(G, A, B, C, D, w5, 0xd62f105d, 5)
220 STEP(G, D, A, B, C, w10, 0x02441453, 9)
221 STEP(G, C, D, A, B, w15, 0xd8a1e681, 14)
222 STEP(G, B, C, D, A, w4, 0xe7d3fbc8, 20)
223 STEP(G, A, B, C, D, w9, 0x21e1cde6, 5)
224 STEP(G, D, A, B, C, w14, 0xc33707d6, 9)
225 STEP(G, C, D, A, B, w3, 0xf4d50d87, 14)
226 STEP(G, B, C, D, A, w8, 0x455a14ed, 20)
227 STEP(G, A, B, C, D, w13, 0xa9e3e905, 5)
228 STEP(G, D, A, B, C, w2, 0xfcefa3f8, 9)
229 STEP(G, C, D, A, B, w7, 0x676f02d9, 14)
230 STEP(G, B, C, D, A, w12, 0x8d2a4c8a, 20)
231
232 /* Round 3 */
233 STEP(H, A, B, C, D, w5, 0xfffa3942, 4)
234 STEP(H2, D, A, B, C, w8, 0x8771f681, 11)
235 STEP(H, C, D, A, B, w11, 0x6d9d6122, 16)
236 STEP(H2, B, C, D, A, w14, 0xfde5380c, 23)
237 STEP(H, A, B, C, D, w1, 0xa4beea44, 4)
238 STEP(H2, D, A, B, C, w4, 0x4bdecfa9, 11)
239 STEP(H, C, D, A, B, w7, 0xf6bb4b60, 16)
240 STEP(H2, B, C, D, A, w10, 0xbebfbc70, 23)
241 STEP(H, A, B, C, D, w13, 0x289b7ec6, 4)
242 STEP(H2, D, A, B, C, w0, 0xeaa127fa, 11)
243 STEP(H, C, D, A, B, w3, 0xd4ef3085, 16)
244 STEP(H2, B, C, D, A, w6, 0x04881d05, 23)
245 STEP(H, A, B, C, D, w9, 0xd9d4d039, 4)
246 STEP(H2, D, A, B, C, w12, 0xe6db99e5, 11)
247 STEP(H, C, D, A, B, w15, 0x1fa27cf8, 16)
248 STEP(H2, B, C, D, A, w2, 0xc4ac5665, 23)
249
250 /* Round 4 */
251 STEP(I, A, B, C, D, w0, 0xf4292244, 6)
252 STEP(I, D, A, B, C, w7, 0x432aff97, 10)
253 STEP(I, C, D, A, B, w14, 0xab9423a7, 15)
254 STEP(I, B, C, D, A, w5, 0xfc93a039, 21)
255 STEP(I, A, B, C, D, w12, 0x655b59c3, 6)
256 STEP(I, D, A, B, C, w3, 0x8f0ccc92, 10)
257 STEP(I, C, D, A, B, w10, 0xffeff47d, 15)
258 STEP(I, B, C, D, A, w1, 0x85845dd1, 21)
259 STEP(I, A, B, C, D, w8, 0x6fa87e4f, 6)
260 STEP(I, D, A, B, C, w15, 0xfe2ce6e0, 10)
261 STEP(I, C, D, A, B, w6, 0xa3014314, 15)
262 STEP(I, B, C, D, A, w13, 0x4e0811a1, 21)
263 STEP(I, A, B, C, D, w4, 0xf7537e82, 6)
264 STEP(I, D, A, B, C, w11, 0xbd3af235, 10)
265 STEP(I, C, D, A, B, w2, 0x2ad7d2bb, 15)
266 STEP(I, B, C, D, A, w9, 0xeb86d391, 21)
267
268 *a = A + sA;
269 *b = B + sB;
270 *c = C + sC;
271 *d = D + sD;
272}
273
274/*
275 * This processes one or more 64-byte data blocks, but does NOT update the bit
276 * counters. There are no alignment requirements.
277 */
278static HOT const void *body(md5_ctx *ctx, const void *data, unsigned long size)
279{
280 const unsigned char *AARU_RESTRICT ptr = (const unsigned char *)data;
281 uint32_t a = ctx->a, b = ctx->b, c = ctx->c, d = ctx->d;
282
283#if (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
284#if MD5_MAX_UNROLL >= 8
285 // 8-block unroll only if total remaining size large enough
286 while(size >= 512 && size >= MD5_UNROLL8_THRESHOLD)
287 {
288#if MD5_ENABLE_PREFETCH
291#endif
292 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 0);
293 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 1);
294 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 2);
295 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 3);
296 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 4);
297 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 5);
298 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 6);
299 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 7);
300 ptr += 512;
301 size -= 512;
302 }
303#endif
304 // 4-block unroll
305 while(size >= 256 && size >= MD5_UNROLL4_THRESHOLD)
306 {
307#if MD5_ENABLE_PREFETCH
310#endif
311 md5_process_block_loaded(&a, &b, &c, &d, ptr);
312 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64);
313 md5_process_block_loaded(&a, &b, &c, &d, ptr + 128);
314 md5_process_block_loaded(&a, &b, &c, &d, ptr + 192);
315 ptr += 256;
316 size -= 256;
317 }
318 // 2-block unroll
319 while(size >= 128 && size >= MD5_UNROLL2_THRESHOLD)
320 {
321#if MD5_ENABLE_PREFETCH
323#endif
324 md5_process_block_loaded(&a, &b, &c, &d, ptr);
325 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64);
326 ptr += 128;
327 size -= 128;
328 }
329 // Single block
330 while(size >= 64)
331 {
332#if MD5_ENABLE_PREFETCH
333 if(size >= 64 * (MD5_PREFETCH_DISTANCE_BLOCKS))
334 {
336 AARU_PREFETCH(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS / 2 + 2));
337 }
338#endif
339 md5_process_block_loaded(&a, &b, &c, &d, ptr);
340 ptr += 64;
341 size -= 64;
342 }
343#else
344 // Fallback original loop
345 uint32_t saved_a, saved_b, saved_c, saved_d;
346 const unsigned char *p2 = ptr;
347 unsigned long sz = size;
348 while(sz >= 64)
349 {
350 if(sz >= 64 * 8)
351 {
352#if defined(__SSE2__) || defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) || \
353 defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
354 AARU_PREFETCH(p2 + 64 * 4);
355 AARU_PREFETCH(p2 + 64 * 6);
356#endif
357 }
358 saved_a = a;
359 saved_b = b;
360 saved_c = c;
361 saved_d = d;
362 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
363 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
364 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
365 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
366 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
367 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
368 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
369 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
370 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
371 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
372 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
373 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
374 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
375 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
376 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
377 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
378 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
379 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
380 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
381 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
382 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
383 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
384 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
385 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
386 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
387 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
388 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
389 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
390 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
391 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
392 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
393 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
394 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
395 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
396 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
397 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
398 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
399 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
400 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
401 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
402 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
403 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
404 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
405 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
406 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
407 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
408 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
409 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
410 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
411 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
412 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
413 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
414 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
415 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
416 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
417 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
418 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
419 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
420 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
421 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
422 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
423 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
424 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
425 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
426 a += saved_a;
427 b += saved_b;
428 c += saved_c;
429 d += saved_d;
430 p2 += 64;
431 sz -= 64;
432 }
433 ptr = p2;
434 size = sz;
435#endif
436
437 ctx->a = a;
438 ctx->b = b;
439 ctx->c = c;
440 ctx->d = d;
441 return ptr;
442}
443
445{
446 ctx->a = 0x67452301;
447 ctx->b = 0xefcdab89;
448 ctx->c = 0x98badcfe;
449 ctx->d = 0x10325476;
450
451 ctx->lo = 0;
452 ctx->hi = 0;
453}
454
455AARU_EXPORT void AARU_CALL aaruf_md5_update(md5_ctx *ctx, const void *AARU_RESTRICT data, unsigned long size)
456{
457
458 const uint32_t saved_lo = ctx->lo;
459 if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++;
460 ctx->hi += size >> 29;
461
462 const unsigned long used = saved_lo & 0x3f;
463
464 if(UNLIKELY(used))
465 {
466 unsigned long available = 64 - used;
467 if(size < available)
468 {
469 memcpy(&ctx->buffer[used], data, size);
470 return;
471 }
472 memcpy(&ctx->buffer[used], data, available);
473 data = (const unsigned char *)data + available;
474 size -= available;
475 body(ctx, ctx->buffer, 64);
476 }
477
478 if(LIKELY(size >= 64))
479 {
480 data = body(ctx, data, size & ~(unsigned long)0x3f);
481 size &= 0x3f;
482 }
483
484 if(size) memcpy(ctx->buffer, data, size);
485}
486
487#define OUT(dst, src) \
488 (dst)[0] = (unsigned char)(src); \
489 (dst)[1] = (unsigned char)((src) >> 8); \
490 (dst)[2] = (unsigned char)((src) >> 16); \
491 (dst)[3] = (unsigned char)((src) >> 24);
492
493AARU_EXPORT void AARU_CALL aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
494{
495
496 unsigned long used = ctx->lo & 0x3f;
497
498 ctx->buffer[used++] = 0x80;
499
500 unsigned long available = 64 - used;
501
502 if(available < 8)
503 {
504 memset(&ctx->buffer[used], 0, available);
505 body(ctx, ctx->buffer, 64);
506 used = 0;
507 available = 64;
508 }
509
510 memset(&ctx->buffer[used], 0, available - 8);
511
512 ctx->lo <<= 3;
513 OUT(&ctx->buffer[56], ctx->lo)
514 OUT(&ctx->buffer[60], ctx->hi)
515
516 body(ctx, ctx->buffer, 64);
517
518 OUT(&result[0], ctx->a)
519 OUT(&result[4], ctx->b)
520 OUT(&result[8], ctx->c)
521 OUT(&result[12], ctx->d)
522
523 memset(ctx, 0, sizeof(*ctx));
524}
525
526AARU_EXPORT void AARU_CALL aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
527{
528 md5_ctx ctx;
529 aaruf_md5_init(&ctx);
530 aaruf_md5_update(&ctx, data, size);
531 aaruf_md5_final(&ctx, result);
532}
#define AARU_CALL
Definition decls.h:46
#define AARU_EXPORT
Definition decls.h:55
#define FORCE_INLINE
Definition decls.h:64
void aaruf_md5_init(md5_ctx *ctx)
Definition md5.c:444
#define HOT
Definition md5.c:65
#define GET(n)
Definition md5.c:165
#define AARU_PREFETCH(addr)
Definition md5.c:84
#define STEP(f, a, b, c, d, x, t, s)
Definition md5.c:138
void aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
Definition md5.c:493
void aaruf_md5_update(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:455
#define AARU_RESTRICT
Definition md5.c:49
#define SET(n)
Definition md5.c:162
FORCE_INLINE void md5_process_block_loaded(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, const unsigned char *ptr)
Definition md5.c:172
#define F(x, y, z)
Definition md5.c:115
#define OUT(dst, src)
Definition md5.c:487
static const void * body(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:278
#define UNLIKELY(x)
Definition md5.c:58
void aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
Definition md5.c:526
#define I(x, y, z)
Definition md5.c:119
#define MD5_PREFETCH_DISTANCE_BLOCKS
Definition md5.c:72
#define MD5_UNROLL8_THRESHOLD
Definition md5.c:88
#define G(x, y, z)
Definition md5.c:116
#define H(x, y, z)
Definition md5.c:117
#define MD5_UNROLL2_THRESHOLD
Definition md5.c:94
#define H2(x, y, z)
Definition md5.c:118
#define MD5_UNROLL4_THRESHOLD
Definition md5.c:91
#define LIKELY(x)
Definition md5.c:57
Definition md5.h:32
uint32_t a
Definition md5.h:34
uint32_t b
Definition md5.h:34
unsigned char buffer[64]
Definition md5.h:35
uint32_t d
Definition md5.h:34
uint32_t hi
Definition md5.h:33
uint32_t c
Definition md5.h:34
uint32_t lo
Definition md5.h:33