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