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 MD5_UNROLL8_THRESHOLD
78#define MD5_UNROLL8_THRESHOLD 8192UL
79#endif
80#ifndef MD5_UNROLL4_THRESHOLD
81#define MD5_UNROLL4_THRESHOLD 2048UL
82#endif
83#ifndef MD5_UNROLL2_THRESHOLD
84#define MD5_UNROLL2_THRESHOLD 512UL
85#endif
86
87#include "decls.h"
88#include "md5.h"
89
90#if defined(__ARM_NEON) || defined(__ARM_NEON__)
91#include <arm_neon.h>
92#endif
93#if defined(__SSE2__) || defined(__AVX2__) || defined(__SSSE3__) || defined(__SSE4_1__) || defined(__x86_64__) || \
94 defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
95#include <immintrin.h>
96#endif
97
98/*
99 * The basic MD5 functions.
100 *
101 * F and G are optimized compared to their RFC 1321 definitions for
102 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
103 * implementation.
104 */
105#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
106#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
107#define H(x, y, z) (((x) ^ (y)) ^ (z))
108#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
109#define I(x, y, z) ((y) ^ ((x) | ~(z)))
110
111/* Rotate-left helper using compiler intrinsics when available */
112#if defined(_MSC_VER)
113#define ROTL32(x, s) _rotl((x), (s))
114#else
115#if defined(__has_builtin)
116#if __has_builtin(__builtin_rotateleft32)
117#define ROTL32(x, s) __builtin_rotateleft32((x), (s))
118#endif
119#endif
120#endif
121#ifndef ROTL32
122#define ROTL32(x, s) (((uint32_t)(x) << (s)) | ((uint32_t)(x) >> (32 - (s))))
123#endif
124
125/*
126 * The MD5 transformation for all four rounds.
127 */
128#define STEP(f, a, b, c, d, x, t, s) \
129 (a) += f((b), (c), (d)) + (x) + (uint32_t)(t); \
130 (a) = ROTL32((a), (s)); \
131 (a) += (b);
132
133/*
134 * SET reads 4 input bytes in little-endian byte order and stores them in a
135 * properly aligned word in host byte order.
136 *
137 * The check for little-endian architectures that tolerate unaligned memory
138 * accesses is just an optimization. Nothing will break if it fails to detect
139 * a suitable architecture.
140 *
141 * Unfortunately, this optimization may be a C strict aliasing rules violation
142 * if the caller's data buffer has effective type that cannot be aliased by
143 * uint32_t. In practice, this problem may occur if these MD5 routines are
144 * inlined into a calling function, or with future and dangerously advanced
145 * link-time optimizations. For the time being, keeping these MD5 routines in
146 * their own translation unit avoids the problem.
147 */
148#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
149#define SET(n) (*(uint32_t *)&ptr[(n) * 4])
150#define GET(n) SET(n)
151#else
152#define SET(n) \
153 (ctx->block[(n)] = (uint32_t)ptr[(n) * 4] | ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
154 ((uint32_t)ptr[(n) * 4 + 2] << 16) | ((uint32_t)ptr[(n) * 4 + 3] << 24))
155#define GET(n) (ctx->block[(n)])
156#endif
157
158/*
159 * This processes one or more 64-byte data blocks, but does NOT update the bit
160 * counters. There are no alignment requirements.
161 */
162static FORCE_INLINE HOT void md5_process_block_loaded(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
163 const unsigned char * AARU_RESTRICT ptr)
164{
165 const uint32_t *wp = (const uint32_t *)ptr; // unaligned ok on supported arch (we gate optimized path)
166 uint32_t A = *a, B = *b, C = *c, D = *d;
167 uint32_t w0 = wp[0];
168 uint32_t w1 = wp[1];
169 uint32_t w2 = wp[2];
170 uint32_t w3 = wp[3];
171 uint32_t w4 = wp[4];
172 uint32_t w5 = wp[5];
173 uint32_t w6 = wp[6];
174 uint32_t w7 = wp[7];
175 uint32_t w8 = wp[8];
176 uint32_t w9 = wp[9];
177 uint32_t w10 = wp[10];
178 uint32_t w11 = wp[11];
179 uint32_t w12 = wp[12];
180 uint32_t w13 = wp[13];
181 uint32_t w14 = wp[14];
182 uint32_t w15 = wp[15];
183
184 uint32_t sA = A, sB = B, sC = C, sD = D;
185
186 /* Round 1 */
187 STEP(F, A, B, C, D, w0, 0xd76aa478, 7)
188 STEP(F, D, A, B, C, w1, 0xe8c7b756, 12)
189 STEP(F, C, D, A, B, w2, 0x242070db, 17)
190 STEP(F, B, C, D, A, w3, 0xc1bdceee, 22)
191 STEP(F, A, B, C, D, w4, 0xf57c0faf, 7)
192 STEP(F, D, A, B, C, w5, 0x4787c62a, 12)
193 STEP(F, C, D, A, B, w6, 0xa8304613, 17)
194 STEP(F, B, C, D, A, w7, 0xfd469501, 22)
195 STEP(F, A, B, C, D, w8, 0x698098d8, 7)
196 STEP(F, D, A, B, C, w9, 0x8b44f7af, 12)
197 STEP(F, C, D, A, B, w10, 0xffff5bb1, 17)
198 STEP(F, B, C, D, A, w11, 0x895cd7be, 22)
199 STEP(F, A, B, C, D, w12, 0x6b901122, 7)
200 STEP(F, D, A, B, C, w13, 0xfd987193, 12)
201 STEP(F, C, D, A, B, w14, 0xa679438e, 17)
202 STEP(F, B, C, D, A, w15, 0x49b40821, 22)
203
204 /* Round 2 */
205 STEP(G, A, B, C, D, w1, 0xf61e2562, 5)
206 STEP(G, D, A, B, C, w6, 0xc040b340, 9)
207 STEP(G, C, D, A, B, w11, 0x265e5a51, 14)
208 STEP(G, B, C, D, A, w0, 0xe9b6c7aa, 20)
209 STEP(G, A, B, C, D, w5, 0xd62f105d, 5)
210 STEP(G, D, A, B, C, w10, 0x02441453, 9)
211 STEP(G, C, D, A, B, w15, 0xd8a1e681, 14)
212 STEP(G, B, C, D, A, w4, 0xe7d3fbc8, 20)
213 STEP(G, A, B, C, D, w9, 0x21e1cde6, 5)
214 STEP(G, D, A, B, C, w14, 0xc33707d6, 9)
215 STEP(G, C, D, A, B, w3, 0xf4d50d87, 14)
216 STEP(G, B, C, D, A, w8, 0x455a14ed, 20)
217 STEP(G, A, B, C, D, w13, 0xa9e3e905, 5)
218 STEP(G, D, A, B, C, w2, 0xfcefa3f8, 9)
219 STEP(G, C, D, A, B, w7, 0x676f02d9, 14)
220 STEP(G, B, C, D, A, w12, 0x8d2a4c8a, 20)
221
222 /* Round 3 */
223 STEP(H, A, B, C, D, w5, 0xfffa3942, 4)
224 STEP(H2, D, A, B, C, w8, 0x8771f681, 11)
225 STEP(H, C, D, A, B, w11, 0x6d9d6122, 16)
226 STEP(H2, B, C, D, A, w14, 0xfde5380c, 23)
227 STEP(H, A, B, C, D, w1, 0xa4beea44, 4)
228 STEP(H2, D, A, B, C, w4, 0x4bdecfa9, 11)
229 STEP(H, C, D, A, B, w7, 0xf6bb4b60, 16)
230 STEP(H2, B, C, D, A, w10, 0xbebfbc70, 23)
231 STEP(H, A, B, C, D, w13, 0x289b7ec6, 4)
232 STEP(H2, D, A, B, C, w0, 0xeaa127fa, 11)
233 STEP(H, C, D, A, B, w3, 0xd4ef3085, 16)
234 STEP(H2, B, C, D, A, w6, 0x04881d05, 23)
235 STEP(H, A, B, C, D, w9, 0xd9d4d039, 4)
236 STEP(H2, D, A, B, C, w12, 0xe6db99e5, 11)
237 STEP(H, C, D, A, B, w15, 0x1fa27cf8, 16)
238 STEP(H2, B, C, D, A, w2, 0xc4ac5665, 23)
239
240 /* Round 4 */
241 STEP(I, A, B, C, D, w0, 0xf4292244, 6)
242 STEP(I, D, A, B, C, w7, 0x432aff97, 10)
243 STEP(I, C, D, A, B, w14, 0xab9423a7, 15)
244 STEP(I, B, C, D, A, w5, 0xfc93a039, 21)
245 STEP(I, A, B, C, D, w12, 0x655b59c3, 6)
246 STEP(I, D, A, B, C, w3, 0x8f0ccc92, 10)
247 STEP(I, C, D, A, B, w10, 0xffeff47d, 15)
248 STEP(I, B, C, D, A, w1, 0x85845dd1, 21)
249 STEP(I, A, B, C, D, w8, 0x6fa87e4f, 6)
250 STEP(I, D, A, B, C, w15, 0xfe2ce6e0, 10)
251 STEP(I, C, D, A, B, w6, 0xa3014314, 15)
252 STEP(I, B, C, D, A, w13, 0x4e0811a1, 21)
253 STEP(I, A, B, C, D, w4, 0xf7537e82, 6)
254 STEP(I, D, A, B, C, w11, 0xbd3af235, 10)
255 STEP(I, C, D, A, B, w2, 0x2ad7d2bb, 15)
256 STEP(I, B, C, D, A, w9, 0xeb86d391, 21)
257
258 *a = A + sA;
259 *b = B + sB;
260 *c = C + sC;
261 *d = D + sD;
262}
263
264/*
265 * This processes one or more 64-byte data blocks, but does NOT update the bit
266 * counters. There are no alignment requirements.
267 */
268static HOT const void *body(md5_ctx *ctx, const void *data, unsigned long size)
269{
270 const unsigned char * AARU_RESTRICT ptr = (const unsigned char *)data;
271 uint32_t a = ctx->a, b = ctx->b, c = ctx->c, d = ctx->d;
272
273#if (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
274#if MD5_MAX_UNROLL >= 8
275 // 8-block unroll only if total remaining size large enough
276 while(size >= 512 && size >= MD5_UNROLL8_THRESHOLD)
277 {
278#if MD5_ENABLE_PREFETCH
279 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS + 8), 0, 3);
280 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS + 10), 0, 3);
281#endif
282 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 0);
283 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 1);
284 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 2);
285 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 3);
286 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 4);
287 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 5);
288 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 6);
289 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64 * 7);
290 ptr += 512;
291 size -= 512;
292 }
293#endif
294 // 4-block unroll
295 while(size >= 256 && size >= MD5_UNROLL4_THRESHOLD)
296 {
297#if MD5_ENABLE_PREFETCH
298 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS), 0, 3);
299 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS + 2), 0, 3);
300#endif
301 md5_process_block_loaded(&a, &b, &c, &d, ptr);
302 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64);
303 md5_process_block_loaded(&a, &b, &c, &d, ptr + 128);
304 md5_process_block_loaded(&a, &b, &c, &d, ptr + 192);
305 ptr += 256;
306 size -= 256;
307 }
308 // 2-block unroll
309 while(size >= 128 && size >= MD5_UNROLL2_THRESHOLD)
310 {
311#if MD5_ENABLE_PREFETCH
312 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS - 2), 0, 3);
313#endif
314 md5_process_block_loaded(&a, &b, &c, &d, ptr);
315 md5_process_block_loaded(&a, &b, &c, &d, ptr + 64);
316 ptr += 128;
317 size -= 128;
318 }
319 // Single block
320 while(size >= 64)
321 {
322#if MD5_ENABLE_PREFETCH
323 if(size >= 64 * (MD5_PREFETCH_DISTANCE_BLOCKS))
324 {
325 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS/2), 0, 3);
326 __builtin_prefetch(ptr + 64 * (MD5_PREFETCH_DISTANCE_BLOCKS/2 + 2), 0, 3);
327 }
328#endif
329 md5_process_block_loaded(&a, &b, &c, &d, ptr);
330 ptr += 64;
331 size -= 64;
332 }
333#else
334 // Fallback original loop
335 uint32_t saved_a, saved_b, saved_c, saved_d;
336 const unsigned char *p2 = ptr;
337 unsigned long sz = size;
338 while(sz >= 64)
339 {
340 if(sz >= 64 * 8)
341 {
342#if defined(__SSE2__) || defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
343 __builtin_prefetch(p2 + 64 * 4, 0, 3);
344 __builtin_prefetch(p2 + 64 * 6, 0, 3);
345#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
346 __builtin_prefetch((const void *)(p2 + 64 * 4));
347 __builtin_prefetch((const void *)(p2 + 64 * 6));
348#endif
349 }
350 saved_a = a; saved_b = b; saved_c = c; saved_d = d;
351 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
352 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
353 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
354 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
355 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
356 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
357 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
358 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
359 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
360 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
361 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
362 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
363 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
364 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
365 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
366 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
367 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
368 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
369 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
370 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
371 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
372 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
373 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
374 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
375 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
376 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
377 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
378 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
379 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
380 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
381 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
382 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
383 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
384 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
385 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
386 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
387 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
388 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
389 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
390 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
391 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
392 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
393 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
394 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
395 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
396 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
397 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
398 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
399 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
400 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
401 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
402 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
403 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
404 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
405 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
406 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
407 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
408 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
409 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
410 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
411 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
412 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
413 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
414 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
415 a += saved_a; b += saved_b; c += saved_c; d += saved_d;
416 p2 += 64; sz -= 64;
417 }
418 ptr = p2; size = sz;
419#endif
420
421 ctx->a = a; ctx->b = b; ctx->c = c; ctx->d = d;
422 return ptr;
423}
424
426{
427 ctx->a = 0x67452301;
428 ctx->b = 0xefcdab89;
429 ctx->c = 0x98badcfe;
430 ctx->d = 0x10325476;
431
432 ctx->lo = 0;
433 ctx->hi = 0;
434}
435
436AARU_EXPORT void AARU_CALL aaruf_md5_update(md5_ctx *ctx, const void * AARU_RESTRICT data, unsigned long size)
437{
438
439 const uint32_t saved_lo = ctx->lo;
440 if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++;
441 ctx->hi += size >> 29;
442
443 const unsigned long used = saved_lo & 0x3f;
444
445 if(UNLIKELY(used))
446 {
447 unsigned long available = 64 - used;
448 if(size < available)
449 {
450 memcpy(&ctx->buffer[used], data, size);
451 return;
452 }
453 memcpy(&ctx->buffer[used], data, available);
454 data = (const unsigned char *)data + available;
455 size -= available;
456 body(ctx, ctx->buffer, 64);
457 }
458
459 if(LIKELY(size >= 64))
460 {
461 data = body(ctx, data, size & ~(unsigned long)0x3f);
462 size &= 0x3f;
463 }
464
465 if(size)
466 memcpy(ctx->buffer, data, size);
467}
468
469#define OUT(dst, src) \
470 (dst)[0] = (unsigned char)(src); \
471 (dst)[1] = (unsigned char)((src) >> 8); \
472 (dst)[2] = (unsigned char)((src) >> 16); \
473 (dst)[3] = (unsigned char)((src) >> 24);
474
475AARU_EXPORT void AARU_CALL aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
476{
477
478 unsigned long used = ctx->lo & 0x3f;
479
480 ctx->buffer[used++] = 0x80;
481
482 unsigned long available = 64 - used;
483
484 if(available < 8)
485 {
486 memset(&ctx->buffer[used], 0, available);
487 body(ctx, ctx->buffer, 64);
488 used = 0;
489 available = 64;
490 }
491
492 memset(&ctx->buffer[used], 0, available - 8);
493
494 ctx->lo <<= 3;
495 OUT(&ctx->buffer[56], ctx->lo)
496 OUT(&ctx->buffer[60], ctx->hi)
497
498 body(ctx, ctx->buffer, 64);
499
500 OUT(&result[0], ctx->a)
501 OUT(&result[4], ctx->b)
502 OUT(&result[8], ctx->c)
503 OUT(&result[12], ctx->d)
504
505 memset(ctx, 0, sizeof(*ctx));
506}
507
508AARU_EXPORT void AARU_CALL aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
509{
510 md5_ctx ctx;
511 aaruf_md5_init(&ctx);
512 aaruf_md5_update(&ctx, data, size);
513 aaruf_md5_final(&ctx, result);
514}
#define AARU_CALL
Definition decls.h:45
#define AARU_EXPORT
Definition decls.h:54
#define FORCE_INLINE
Definition decls.h:63
void aaruf_md5_init(md5_ctx *ctx)
Definition md5.c:425
#define HOT
Definition md5.c:65
#define GET(n)
Definition md5.c:155
#define STEP(f, a, b, c, d, x, t, s)
Definition md5.c:128
void aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
Definition md5.c:475
void aaruf_md5_update(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:436
#define AARU_RESTRICT
Definition md5.c:49
static 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:162
#define SET(n)
Definition md5.c:152
#define F(x, y, z)
Definition md5.c:105
#define OUT(dst, src)
Definition md5.c:469
static const void * body(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:268
#define UNLIKELY(x)
Definition md5.c:58
void aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
Definition md5.c:508
#define I(x, y, z)
Definition md5.c:109
#define MD5_PREFETCH_DISTANCE_BLOCKS
Definition md5.c:72
#define MD5_UNROLL8_THRESHOLD
Definition md5.c:78
#define G(x, y, z)
Definition md5.c:106
#define H(x, y, z)
Definition md5.c:107
#define MD5_UNROLL2_THRESHOLD
Definition md5.c:84
#define H2(x, y, z)
Definition md5.c:108
#define MD5_UNROLL4_THRESHOLD
Definition md5.c:81
#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