The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/** A local MD5 implementation
2 *
3 * @note license is LGPL, but largely derived from a public domain source.
4 *
5 * @file src/lib/util/md5.c
6 */
7RCSID("$Id: b236a4acb6bb1283a1c656c7a3dba5693d379fb3 $")
8
9#include <freeradius-devel/util/debug.h>
10#include <freeradius-devel/util/strerror.h>
11#include <freeradius-devel/util/atexit.h>
12
13/*
14 * FORCE MD5 TO USE OUR MD5 HEADER FILE!
15 * If we don't do this, it might pick up the systems broken MD5.
16 */
17#include <freeradius-devel/util/md5.h>
18
19/** The thread local free list
20 *
21 * Any entries remaining in the list will be freed when the thread is joined
22 */
23#define ARRAY_SIZE (8)
24typedef struct {
25 bool used;
28static _Thread_local fr_md5_free_list_t *md5_array;
29
30static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx);
31static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src);
33static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx);
34static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen);
36
46
47/*
48 * If we have OpenSSL's EVP API available, then build wrapper functions.
49 *
50 * We always need to build the local MD5 functions as OpenSSL could
51 * be operating in FIPS mode where MD5 digest functions are unavailable.
52 */
53#ifdef HAVE_OPENSSL_EVP_H
54# include <freeradius-devel/tls/openssl_user_macros.h>
55# include <openssl/evp.h>
56# include <openssl/crypto.h>
57# include <openssl/err.h>
58# include <openssl/provider.h>
59
60/** @copydoc fr_md5_ctx_reset
61 *
62 */
63static void fr_md5_openssl_ctx_reset(fr_md5_ctx_t *ctx)
64{
65 EVP_MD_CTX *md_ctx = ctx;
66
67 EVP_MD_CTX_reset(md_ctx);
68 (void)EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL);
69}
70
71/** @copydoc fr_md5_ctx_copy
72 *
73 */
74static void fr_md5_openssl_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
75{
76 EVP_MD_CTX_copy_ex(dst, src);
77}
78
79/** @copydoc fr_md5_ctx_alloc
80 *
81 */
82static fr_md5_ctx_t *fr_md5_openssl_ctx_alloc(void)
83{
84 EVP_MD_CTX *md_ctx;
85
86 md_ctx = EVP_MD_CTX_new();
87 if (unlikely(!md_ctx)) return NULL;
88
89 if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL) != 1) {
90 char buffer[256];
91
92 ERR_error_string_n(ERR_get_error(), buffer, sizeof(buffer));
93 fr_strerror_printf("Failed initialising MD5 ctx: %s", buffer);
94 EVP_MD_CTX_free(md_ctx);
95
96 return NULL;
97 }
98
99 return md_ctx;
100}
101
102/** @copydoc fr_md5_ctx_free
103 *
104 */
105static void fr_md5_openssl_ctx_free(fr_md5_ctx_t **ctx)
106{
107 if (!*ctx) return;
108
109 EVP_MD_CTX_free(*ctx);
110 *ctx = NULL;
111}
112
113/** @copydoc fr_md5_update
114 *
115 */
116static void fr_md5_openssl_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
117{
118 EVP_DigestUpdate(ctx, in, inlen);
119}
120
121/** @copydoc fr_md5_final
122 *
123 */
124static void fr_md5_openssl_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
125{
126 unsigned int len;
127
128 EVP_DigestFinal(ctx, out, &len);
129
130 if (!fr_cond_assert(len == MD5_DIGEST_LENGTH)) return;
131}
132
133static fr_md5_funcs_t md5_openssl_funcs = {
134 .reset = fr_md5_openssl_ctx_reset,
135 .copy = fr_md5_openssl_ctx_copy,
136 .alloc = fr_md5_openssl_ctx_alloc,
137 .free = fr_md5_openssl_ctx_free,
138 .update = fr_md5_openssl_update,
139 .final = fr_md5_openssl_final
140};
141#endif
142
143# define MD5_BLOCK_LENGTH 64
144typedef struct {
145 uint32_t state[4]; //!< State.
146 uint32_t count[2]; //!< Number of bits, mod 2^64.
147 uint8_t buffer[MD5_BLOCK_LENGTH]; //!< Input buffer.
149
150/*
151 * This code implements the MD5 message-digest algorithm.
152 * The algorithm is due to Ron Rivest. This code was
153 * written by Colin Plumb in 1993, no copyright is claimed.
154 * This code is in the public domain; do with it what you wish.
155 *
156 * Equivalent code is available from RSA Data Security, Inc.
157 * This code has been tested against that, and is equivalent,
158 * except that you don't need to include two pages of legalese
159 * with every copy.
160 *
161 * To compute the message digest of a chunk of bytes, declare an
162 * MD5Context structure, pass it to fr_md5_init, call fr_md5_update as
163 * needed on buffers full of bytes, and then call fr_md5_final, which
164 * will fill a supplied 16-byte array with the digest.
165 */
166#define PUT_64BIT_LE(cp, value) do {\
167 (cp)[7] = (value)[1] >> 24;\
168 (cp)[6] = (value)[1] >> 16;\
169 (cp)[5] = (value)[1] >> 8;\
170 (cp)[4] = (value)[1];\
171 (cp)[3] = (value)[0] >> 24;\
172 (cp)[2] = (value)[0] >> 16;\
173 (cp)[1] = (value)[0] >> 8;\
174 (cp)[0] = (value)[0];\
175} while (0)
176
177#define PUT_32BIT_LE(cp, value) do {\
178 (cp)[3] = (value) >> 24;\
179 (cp)[2] = (value) >> 16;\
180 (cp)[1] = (value) >> 8;\
181 (cp)[0] = (value);\
182} while (0)
183
185 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
188};
189
190
191/* The four core functions - MD5_F1 is optimized somewhat */
192#define MD5_F1(x, y, z) (z ^ (x & (y ^ z)))
193#define MD5_F2(x, y, z) MD5_F1(z, x, y)
194#define MD5_F3(x, y, z) (x ^ y ^ z)
195#define MD5_F4(x, y, z) (y ^ (x | ~z))
196
197/* This is the central step in the MD5 algorithm. */
198#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
199
200/** The core of the MD5 algorithm
201 *
202 * This alters an existing MD5 hash to reflect the addition of 16
203 * longwords of new data. fr_md5_update blocks the data and converts bytes
204 * into longwords for this routine.
205 *
206 * @param[in] state 16 bytes of data to feed into the hashing function.
207 * @param[in,out] block MD5 digest block to update.
208 */
209static void fr_md5_local_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
210{
211 uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
212
213 for (a = 0; a < (MD5_BLOCK_LENGTH / 4); a++) {
214 size_t idx = a * 4;
215
216 in[a] = (uint32_t)(
217 (uint32_t)(block[idx + 0]) |
218 (uint32_t)(block[idx + 1]) << 8 |
219 (uint32_t)(block[idx + 2]) << 16 |
220 (uint32_t)(block[idx + 3]) << 24);
221 }
222
223 a = state[0];
224 b = state[1];
225 c = state[2];
226 d = state[3];
227
228 MD5STEP(MD5_F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
229 MD5STEP(MD5_F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
230 MD5STEP(MD5_F1, c, d, a, b, in[ 2] + 0x242070db, 17);
231 MD5STEP(MD5_F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
232 MD5STEP(MD5_F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
233 MD5STEP(MD5_F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
234 MD5STEP(MD5_F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
235 MD5STEP(MD5_F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
236 MD5STEP(MD5_F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
237 MD5STEP(MD5_F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
238 MD5STEP(MD5_F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
239 MD5STEP(MD5_F1, b, c, d, a, in[11] + 0x895cd7be, 22);
240 MD5STEP(MD5_F1, a, b, c, d, in[12] + 0x6b901122, 7);
241 MD5STEP(MD5_F1, d, a, b, c, in[13] + 0xfd987193, 12);
242 MD5STEP(MD5_F1, c, d, a, b, in[14] + 0xa679438e, 17);
243 MD5STEP(MD5_F1, b, c, d, a, in[15] + 0x49b40821, 22);
244
245 MD5STEP(MD5_F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
246 MD5STEP(MD5_F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
247 MD5STEP(MD5_F2, c, d, a, b, in[11] + 0x265e5a51, 14);
248 MD5STEP(MD5_F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
249 MD5STEP(MD5_F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
250 MD5STEP(MD5_F2, d, a, b, c, in[10] + 0x02441453, 9);
251 MD5STEP(MD5_F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
252 MD5STEP(MD5_F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
253 MD5STEP(MD5_F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
254 MD5STEP(MD5_F2, d, a, b, c, in[14] + 0xc33707d6, 9);
255 MD5STEP(MD5_F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
256 MD5STEP(MD5_F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
257 MD5STEP(MD5_F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
258 MD5STEP(MD5_F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
259 MD5STEP(MD5_F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
260 MD5STEP(MD5_F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
261
262 MD5STEP(MD5_F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
263 MD5STEP(MD5_F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
264 MD5STEP(MD5_F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
265 MD5STEP(MD5_F3, b, c, d, a, in[14] + 0xfde5380c, 23);
266 MD5STEP(MD5_F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
267 MD5STEP(MD5_F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
268 MD5STEP(MD5_F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
269 MD5STEP(MD5_F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
270 MD5STEP(MD5_F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
271 MD5STEP(MD5_F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
272 MD5STEP(MD5_F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
273 MD5STEP(MD5_F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
274 MD5STEP(MD5_F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
275 MD5STEP(MD5_F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
276 MD5STEP(MD5_F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
277 MD5STEP(MD5_F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
278
279 MD5STEP(MD5_F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
280 MD5STEP(MD5_F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
281 MD5STEP(MD5_F4, c, d, a, b, in[14] + 0xab9423a7, 15);
282 MD5STEP(MD5_F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
283 MD5STEP(MD5_F4, a, b, c, d, in[12] + 0x655b59c3, 6);
284 MD5STEP(MD5_F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
285 MD5STEP(MD5_F4, c, d, a, b, in[10] + 0xffeff47d, 15);
286 MD5STEP(MD5_F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
287 MD5STEP(MD5_F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6);
288 MD5STEP(MD5_F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
289 MD5STEP(MD5_F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
290 MD5STEP(MD5_F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
291 MD5STEP(MD5_F4, a, b, c, d, in[4 ] + 0xf7537e82, 6);
292 MD5STEP(MD5_F4, d, a, b, c, in[11] + 0xbd3af235, 10);
293 MD5STEP(MD5_F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
294 MD5STEP(MD5_F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
295
296 state[0] += a;
297 state[1] += b;
298 state[2] += c;
299 state[3] += d;
300}
301
302/** @copydoc fr_md5_ctx_reset
303 *
304 */
306{
307 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
308
309 ctx_local->count[0] = 0;
310 ctx_local->count[1] = 0;
311 ctx_local->state[0] = 0x67452301;
312 ctx_local->state[1] = 0xefcdab89;
313 ctx_local->state[2] = 0x98badcfe;
314 ctx_local->state[3] = 0x10325476;
315 memset(ctx_local->buffer, 0, sizeof(ctx_local->buffer));
316}
317
318/** @copydoc fr_md5_ctx_copy
319 *
320 */
322{
324 fr_md5_ctx_local_t *ctx_local_dst = talloc_get_type_abort(dst, fr_md5_ctx_local_t);
325
326 memcpy(ctx_local_dst, ctx_local_src, sizeof(*ctx_local_dst));
327}
328
329/** @copydoc fr_md5_ctx_alloc
330 *
331 */
333{
334 fr_md5_ctx_local_t *ctx_local;
335
336 ctx_local = talloc(NULL, fr_md5_ctx_local_t);
337 if (unlikely(!ctx_local)) return NULL;
338 fr_md5_local_ctx_reset(ctx_local);
339
340 return ctx_local;
341}
342
343/** @copydoc fr_md5_ctx_free
344 *
345 */
347{
348 talloc_free(*ctx);
349 *ctx = NULL;
350}
351
352static const uint8_t *zero = (uint8_t[]){ 0x00 };
353
354/** @copydoc fr_md5_update
355 *
356 */
357static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
358{
359 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
360
361 size_t have, need;
362
363 /*
364 * Needed so we can calculate the zero
365 * length md5 hash correctly.
366 * ubsan doesn't like arithmetic on
367 * NULL pointers.
368 */
369 if (!in) {
370 in = zero;
371 inlen = 0;
372 }
373
374 /* Check how many bytes we already have and how many more we need. */
375 have = (size_t)((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
376 need = MD5_BLOCK_LENGTH - have;
377
378 /* Update bitcount */
379/* ctx_local->count += (uint64_t)inlen << 3;*/
380 if ((ctx_local->count[0] += ((uint32_t)inlen << 3)) < (uint32_t)inlen) {
381 /* Overflowed ctx_local->count[0] */
382 ctx_local->count[1]++;
383 }
384 ctx_local->count[1] += ((uint32_t)inlen >> 29);
385
386 if (inlen >= need) {
387 if (have != 0) {
388 memcpy(ctx_local->buffer + have, in, need);
389 fr_md5_local_transform(ctx_local->state, ctx_local->buffer);
390 in += need;
391 inlen -= need;
392 have = 0;
393 }
394
395 /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
396 while (inlen >= MD5_BLOCK_LENGTH) {
397 fr_md5_local_transform(ctx_local->state, in);
400 }
401 }
402
403 /* Handle any remaining bytes of data. */
404 memcpy(ctx_local->buffer + have, in, inlen);
405}
406
407/** @copydoc fr_md5_final
408 *
409 */
411{
412 fr_md5_ctx_local_t *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
413 uint8_t count[8];
414 size_t padlen;
415 int i;
416
417 /* Convert count to 8 bytes in little endian order. */
418 PUT_64BIT_LE(count, ctx_local->count);
419
420 /* Pad out to 56 mod 64. */
421 padlen = MD5_BLOCK_LENGTH -
422 ((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
423 if (padlen < 1 + 8)
424 padlen += MD5_BLOCK_LENGTH;
425 fr_md5_update(ctx_local, PADDING, padlen - 8); /* padlen - 8 <= 64 */
426 fr_md5_update(ctx_local, count, 8);
427
428 for (i = 0; i < 4; i++)
429 PUT_32BIT_LE(out + i * 4, ctx_local->state[i]);
430
431 memset(ctx_local, 0, sizeof(*ctx_local)); /* in case it's sensitive */
432}
433
434/** Calculate the MD5 hash of the contents of a buffer
435 *
436 * @param[out] out Where to write the MD5 digest. Must be a minimum of MD5_DIGEST_LENGTH.
437 * @param[in] in Data to hash.
438 * @param[in] inlen Length of the data.
439 */
441{
442 fr_md5_ctx_t *ctx;
443
445 fr_md5_update(ctx, in, inlen);
446 fr_md5_final(out, ctx);
448}
449
450static int _md5_ctx_free_on_exit(void *arg)
451{
452 int i;
453 fr_md5_free_list_t *free_list = arg;
454
455 for (i = 0; i < ARRAY_SIZE; i++) {
456 if (free_list[i].used) continue;
457
458 fr_md5_ctx_free(&free_list[i].md_ctx);
459 }
460
461 if (talloc_free(free_list) < 0) return -1;
462
463 md5_array = NULL;
464 return 0;
465}
466
467/** @copydoc fr_md5_ctx_alloc
468 *
469 */
471{
472 int i;
473 fr_md5_ctx_t *md_ctx;
474 fr_md5_free_list_t *free_list;
475
476 if (unlikely(!md5_array)) {
477 free_list = talloc_zero_array(NULL, fr_md5_free_list_t, ARRAY_SIZE);
478 if (unlikely(!free_list)) {
479 oom:
480 fr_strerror_const("Out of Memory");
481 return NULL;
482 }
483
485
486 /*
487 * Initialize all MD5 contexts
488 */
489 for (i = 0; i < ARRAY_SIZE; i++) {
490 md_ctx = fr_md5_ctx_alloc();
491 if (unlikely(md_ctx == NULL)) goto oom;
492
493 free_list[i].md_ctx = md_ctx;
494 }
495 } else {
496 free_list = md5_array;
497 }
498
499 for (i = 0; i < ARRAY_SIZE; i++) {
500 if (free_list[i].used) continue;
501
502 free_list[i].used = true;
503 return free_list[i].md_ctx;
504 }
505
506 /*
507 * No more free contexts, just allocate a new one.
508 */
509 return fr_md5_ctx_alloc();
510}
511
512/** @copydoc fr_md5_ctx_free
513 *
514 */
516{
517 int i;
518 fr_md5_free_list_t *free_list = md5_array;
519
520 if (free_list) {
521 for (i = 0; i < ARRAY_SIZE; i++) {
522 if (free_list[i].md_ctx == *ctx) {
523 free_list[i].used = false;
524 fr_md5_ctx_reset(*ctx);
525 *ctx = NULL;
526 return;
527 }
528 }
529 }
530
531 fr_md5_ctx_free(*ctx);
532 *ctx = NULL;
533}
534
535#ifdef HAVE_OPENSSL_EVP_H
536static void md5_free_list_reinit(fr_md5_funcs_t *funcs)
537{
538 int i;
539 fr_md5_ctx_t *md_ctx;
540 fr_md5_free_list_t *free_list = md5_array;
541
542 if (!free_list) {
543 fr_md5_funcs = funcs;
544 return;
545 }
546
547 for (i = 0; i < ARRAY_SIZE; i++) {
548 fr_assert(!free_list[i].used);
549
550 fr_md5_ctx_free(&free_list[i].md_ctx);
551 }
552
553 fr_md5_funcs = funcs;
554
555 for (i = 0; i < ARRAY_SIZE; i++) {
556 md_ctx = fr_md5_ctx_alloc();
557 fr_assert(md_ctx != NULL);
558
559 free_list[i].md_ctx = md_ctx;
560 }
561}
562
563void fr_md5_openssl_init(void)
564{
566
567 /*
568 * If we are in FIPS mode, then we still use the local
569 * allocator.
570 */
571 if (EVP_default_properties_is_fips_enabled(NULL)) return;
572
573 /*
574 * OpenSSL isn't in FIPS mode. Swap out the functions
575 * pointers for the OpenSSL versions.
576 *
577 * We do this by swapping out a pointer to a structure
578 * containing the functions, as this prevents possible
579 * skew where some threads see a mixture of functions.
580 */
581 md5_free_list_reinit(&md5_openssl_funcs);
582}
583
584void fr_md5_openssl_free(void)
585{
586 if (fr_md5_funcs == &md5_local_funcs) return; /* not initialized, or FIPS. */
587
588 md5_free_list_reinit(&md5_local_funcs);
589}
590#endif
static int const char char buffer[256]
Definition acutest.h:576
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:220
#define RCSID(id)
Definition build.h:506
#define unlikely(_x)
Definition build.h:402
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:141
static fr_slen_t in
Definition dict.h:882
talloc_free(hp)
#define MD5_F3(x, y, z)
Definition md5.c:194
#define MD5STEP(f, w, x, y, z, data, s)
Definition md5.c:198
#define MD5_F1(x, y, z)
Definition md5.c:192
fr_md5_ctx_t * md_ctx
Definition md5.c:26
uint32_t state[4]
State.
Definition md5.c:145
static void fr_md5_local_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
The core of the MD5 algorithm.
Definition md5.c:209
#define MD5_F4(x, y, z)
Definition md5.c:195
uint32_t count[2]
Number of bits, mod 2^64.
Definition md5.c:146
static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
Copy the contents of a ctx.
Definition md5.c:321
static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
Ingest plaintext into the digest.
Definition md5.c:357
static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx)
Reset the ctx to allow reuse.
Definition md5.c:305
#define MD5_BLOCK_LENGTH
Definition md5.c:143
#define ARRAY_SIZE
The thread local free list.
Definition md5.c:23
#define PUT_64BIT_LE(cp, value)
Definition md5.c:166
static _Thread_local fr_md5_free_list_t * md5_array
Definition md5.c:28
#define MD5_F2(x, y, z)
Definition md5.c:193
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD5 hash of the contents of a buffer.
Definition md5.c:440
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Free function for MD5 digest ctx.
Definition md5.c:515
static fr_md5_ctx_t * fr_md5_local_ctx_alloc(void)
Allocation function for MD5 digest context.
Definition md5.c:332
static int _md5_ctx_free_on_exit(void *arg)
Definition md5.c:450
static const uint8_t PADDING[MD5_BLOCK_LENGTH]
Definition md5.c:184
fr_md5_funcs_t const * fr_md5_funcs
Swap a single pointer, so all functions get swapped as an atomic operation.
Definition md5.c:45
static fr_md5_funcs_t md5_local_funcs
Definition md5.c:37
static void fr_md5_local_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
Finalise the ctx, producing the digest.
Definition md5.c:410
static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx)
Free function for MD5 digest ctx.
Definition md5.c:346
uint8_t buffer[MD5_BLOCK_LENGTH]
Input buffer.
Definition md5.c:147
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Allocation function for MD5 digest context.
Definition md5.c:470
#define PUT_32BIT_LE(cp, value)
Definition md5.c:177
static const uint8_t * zero
Definition md5.c:352
fr_md5_ctx_reset_t reset
Definition md5.h:37
#define fr_md5_final(_out, _ctx)
Finalise the ctx, producing the digest.
Definition md5.h:90
#define fr_md5_ctx_alloc()
Allocation function for MD5 digest context.
Definition md5.h:68
#define fr_md5_ctx_reset(_ctx)
Reset the ctx to allow reuse.
Definition md5.h:53
void fr_md5_ctx_t
Definition md5.h:25
#define fr_md5_update(_ctx, _in, _inlen)
Ingest plaintext into the digest.
Definition md5.h:83
#define fr_md5_ctx_free(_ctx)
Free function for MD5 digest ctx.
Definition md5.h:75
#define MD5_DIGEST_LENGTH
unsigned int uint32_t
unsigned char uint8_t
unsigned long int size_t
static size_t used
#define fr_assert(_expr)
Definition rad_assert.h:37
return count
Definition module.c:155
#define talloc_get_type_abort_const
Definition talloc.h:110
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1030
static size_t char ** out
Definition value.h:1030