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 */
162 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 */
268 static 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;
351 saved_b = b;
352 saved_c = c;
353 saved_d = d;
354 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
355 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
356 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
357 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
358 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
359 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
360 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
361 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
362 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
363 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
364 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
365 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
366 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
367 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
368 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
369 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
370 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
371 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
372 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
373 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
374 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
375 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
376 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
377 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
378 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
379 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
380 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
381 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
382 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
383 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
384 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
385 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
386 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
387 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
388 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
389 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
390 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
391 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
392 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
393 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
394 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
395 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
396 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
397 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
398 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
399 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
400 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
401 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
402 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
403 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
404 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
405 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
406 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
407 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
408 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
409 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
410 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
411 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
412 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
413 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
414 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
415 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
416 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
417 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
418 a += saved_a;
419 b += saved_b;
420 c += saved_c;
421 d += saved_d;
422 p2 += 64;
423 sz -= 64;
424 }
425 ptr = p2;
426 size = sz;
427#endif
428
429 ctx->a = a;
430 ctx->b = b;
431 ctx->c = c;
432 ctx->d = d;
433 return ptr;
434}
435
436 AARU_EXPORT void AARU_CALL aaruf_md5_init(md5_ctx *ctx)
437{
438 ctx->a = 0x67452301;
439 ctx->b = 0xefcdab89;
440 ctx->c = 0x98badcfe;
441 ctx->d = 0x10325476;
442
443 ctx->lo = 0;
444 ctx->hi = 0;
445}
446
447 AARU_EXPORT void AARU_CALL aaruf_md5_update(md5_ctx *ctx, const void *AARU_RESTRICT data, unsigned long size)
448{
449
450 const uint32_t saved_lo = ctx->lo;
451 if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++;
452 ctx->hi += size >> 29;
453
454 const unsigned long used = saved_lo & 0x3f;
455
456 if(UNLIKELY(used))
457 {
458 unsigned long available = 64 - used;
459 if(size < available)
460 {
461 memcpy(&ctx->buffer[used], data, size);
462 return;
463 }
464 memcpy(&ctx->buffer[used], data, available);
465 data = (const unsigned char *)data + available;
466 size -= available;
467 body(ctx, ctx->buffer, 64);
468 }
469
470 if(LIKELY(size >= 64))
471 {
472 data = body(ctx, data, size & ~(unsigned long)0x3f);
473 size &= 0x3f;
474 }
475
476 if(size) memcpy(ctx->buffer, data, size);
477}
478
479#define OUT(dst, src) \
480 (dst)[0] = (unsigned char)(src); \
481 (dst)[1] = (unsigned char)((src) >> 8); \
482 (dst)[2] = (unsigned char)((src) >> 16); \
483 (dst)[3] = (unsigned char)((src) >> 24);
484
485 AARU_EXPORT void AARU_CALL aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
486{
487
488 unsigned long used = ctx->lo & 0x3f;
489
490 ctx->buffer[used++] = 0x80;
491
492 unsigned long available = 64 - used;
493
494 if(available < 8)
495 {
496 memset(&ctx->buffer[used], 0, available);
497 body(ctx, ctx->buffer, 64);
498 used = 0;
499 available = 64;
500 }
501
502 memset(&ctx->buffer[used], 0, available - 8);
503
504 ctx->lo <<= 3;
505 OUT(&ctx->buffer[56], ctx->lo)
506 OUT(&ctx->buffer[60], ctx->hi)
507
508 body(ctx, ctx->buffer, 64);
509
510 OUT(&result[0], ctx->a)
511 OUT(&result[4], ctx->b)
512 OUT(&result[8], ctx->c)
513 OUT(&result[12], ctx->d)
514
515 memset(ctx, 0, sizeof(*ctx));
516}
517
518 AARU_EXPORT void AARU_CALL aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
519{
520 md5_ctx ctx;
521 aaruf_md5_init(&ctx);
522 aaruf_md5_update(&ctx, data, size);
523 aaruf_md5_final(&ctx, result);
524}
decls.h
AARU_CALL
#define AARU_CALL
Definition decls.h:45
AARU_EXPORT
#define AARU_EXPORT
Definition decls.h:54
FORCE_INLINE
#define FORCE_INLINE
Definition decls.h:63
aaruf_md5_init
void aaruf_md5_init(md5_ctx *ctx)
Definition md5.c:436
HOT
#define HOT
Definition md5.c:65
GET
#define GET(n)
Definition md5.c:155
STEP
#define STEP(f, a, b, c, d, x, t, s)
Definition md5.c:128
aaruf_md5_final
void aaruf_md5_final(md5_ctx *ctx, unsigned char *result)
Definition md5.c:485
aaruf_md5_update
void aaruf_md5_update(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:447
AARU_RESTRICT
#define AARU_RESTRICT
Definition md5.c:49
SET
#define SET(n)
Definition md5.c:152
md5_process_block_loaded
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
F
#define F(x, y, z)
Definition md5.c:105
OUT
#define OUT(dst, src)
Definition md5.c:479
body
static const void * body(md5_ctx *ctx, const void *data, unsigned long size)
Definition md5.c:268
UNLIKELY
#define UNLIKELY(x)
Definition md5.c:58
aaruf_md5_buffer
void aaruf_md5_buffer(const void *data, unsigned long size, unsigned char *result)
Definition md5.c:518
I
#define I(x, y, z)
Definition md5.c:109
MD5_PREFETCH_DISTANCE_BLOCKS
#define MD5_PREFETCH_DISTANCE_BLOCKS
Definition md5.c:72
MD5_UNROLL8_THRESHOLD
#define MD5_UNROLL8_THRESHOLD
Definition md5.c:78
G
#define G(x, y, z)
Definition md5.c:106
H
#define H(x, y, z)
Definition md5.c:107
MD5_UNROLL2_THRESHOLD
#define MD5_UNROLL2_THRESHOLD
Definition md5.c:84
H2
#define H2(x, y, z)
Definition md5.c:108
MD5_UNROLL4_THRESHOLD
#define MD5_UNROLL4_THRESHOLD
Definition md5.c:81
LIKELY
#define LIKELY(x)
Definition md5.c:57
md5.h
md5_ctx
Definition md5.h:32
md5_ctx::a
uint32_t a
Definition md5.h:34
md5_ctx::b
uint32_t b
Definition md5.h:34
md5_ctx::buffer
unsigned char buffer[64]
Definition md5.h:35
md5_ctx::d
uint32_t d
Definition md5.h:34
md5_ctx::hi
uint32_t hi
Definition md5.h:33
md5_ctx::c
uint32_t c
Definition md5.h:34
md5_ctx::lo
uint32_t lo
Definition md5.h:33